ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【ybtoj高效进阶 21185】树上询问(LCT)

2021-11-15 21:30:50  阅读:157  来源: 互联网

标签:进阶 rs int ybtoj void 21185 fa ls now


树上询问

题目链接:ybtoj高效进阶 21185

题目大意

给你一个森林,一开始有 n 个点,然后要支持三个操作:
把一个点定做它树的根,查询一个点子树大小,连接两个不在同一棵树上的点,然后指定其中一个树原来的根是新树的根。

思路

小前言

这题改半天一直都是 5 5 5 分,结果叫别人叫他的 AC 代码也只有 5 5 5 分?!
好我不管了我摆烂了我宣布我 A 了爱改不改。

正式内容

其实就是 LCT 维护子树内容题。

大概就是维护包括实边虚边的子树大小,以及虚边连接的子树大小。

这样维护有什么用呢?
你会发现你可以把实边设做它在森林中的父亲,那你设置根的操作就相当于 access 操作。

然后维护一下即可。

代码

#include<cstdio>
#include<algorithm>

using namespace std;

int n, m, op, x, y, rt;

int re, zf;
char c;

int read() {
	re = 0; zf = 1;
	c = getchar();
	while (c < '0' || c > '9') {
		if (c == '-') zf = -zf;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		re = (re << 3) + (re << 1) + c - '0';
		c = getchar();
	}
	return re * zf;
}

void writee(int now) {
	if (now > 9) writee(now / 10);
	putchar(now % 10 + '0');
}

void write(int now) {
	if (now < 0) putchar('-'), now = -now;
	writee(now);
}

struct LCT {
	int sum[400001], faksz[400001];
	int ls[400001], rs[400001], fa[400001];
	bool lzyt[400001];
	
	bool nrt(int x) {
		return ls[fa[x]] == x || rs[fa[x]] == x;
	}
	
	bool lrs(int x) {
		return ls[fa[x]] == x;
	}
	
	void up(int x) {
		sum[x] = sum[ls[x]] + sum[rs[x]] + faksz[x] + 1;
	}
	
	void downt(int x) {
		swap(ls[x], rs[x]);
		lzyt[x] ^= 1;
	}
	
	void down(int x) {
		if (lzyt[x]) {
			if (ls[x]) downt(ls[x]);
			if (rs[x]) downt(rs[x]);
			lzyt[x] = 0;
		}
	}
	
	void down_line(int x) {
		if (nrt(x)) down_line(fa[x]);
		down(x);
	}
	
	void rotate(int x) {
		int y = fa[x];
		int z = fa[y];
		int b = (lrs(x) ? rs[x] : ls[x]);
		if (z && nrt(y)) (lrs(y) ? ls[z] : rs[z]) = x;
		if (lrs(x)) rs[x] = y, ls[y] = b;
			else ls[x] = y, rs[y] = b;
		fa[x] = z;
		fa[y] = x;
		if (b) fa[b] = y;
		up(y); up(x);
	}
	
	void Splay(int x) {
		down_line(x);
		while (nrt(x)) {
			if (nrt(fa[x])) {
				if (lrs(x) == lrs(fa[x])) rotate(fa[x]);
					else rotate(x);
			}
			rotate(x);
		}
	}
	
	void access(int x) {
		int lst = 0;
		for (; x; x = fa[x]) {
			Splay(x);
			
			faksz[x] += sum[rs[x]] - sum[lst];
			rs[x] = lst;
			up(x);
			lst = x;
		}
	}
	
	int find_root(int x) {
		access(x);
		Splay(x);
		while (down(x), ls[x])
			x = ls[x];
		Splay(x);
		return x;
	}
	
	void make_root(int x) {
		access(x);
		Splay(x);
		downt(x);
	}
	
	void link(int x, int y) {
		make_root(x);
		make_root(y);
		fa[x] = y;
		faksz[y] += sum[x];
		up(y);
	}
}T;

int main() {
	freopen("tree.in", "r", stdin);
	freopen("tree.out", "w", stdout);
	
	n = read(); m = read();
	
	for (int i = 1; i <= n; i++) T.up(i);
	
	while (m--) {
		op = read(); x = read();
		if (op == 1) T.make_root(x);
			else if (op == 2) {
				T.access(x);
				write(T.faksz[x] + 1); putchar('\n');
			}
			else if (op == 3) {
				rt = T.find_root(x);
				y = read();
				T.link(x, y);
				T.make_root(rt);
			}
	}
	
	return 0;
}

标签:进阶,rs,int,ybtoj,void,21185,fa,ls,now
来源: https://blog.csdn.net/weixin_43346722/article/details/121342110

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有