luogu3690 【模板】Link Cut Tree (动态树)

参考therethere
题单

#include <iostream>
#include <cstdio>
using namespace std;
int n, m, val[300005], ch[300005][2], sum[300005], fa[300005], uu, vv, opt;
int rev[300005];
void pushDown(int x){
	if(rev[x]){
		swap(ch[x][0], ch[x][1]);
		rev[ch[x][0]] ^= 1;
		rev[ch[x][1]] ^= 1;
		rev[x] = 0;
	}
}
bool isRoot(int x){
	return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}
void xf(int x){
	if(!isRoot(x))	xf(fa[x]);
	pushDown(x);
}
bool getW(int x){
	return ch[fa[x]][1]==x;
}
void upd(int x){
	sum[x] = sum[ch[x][0]] ^ sum[ch[x][1]] ^ val[x];
}
void rotate(int x){
	int old=fa[x], oldf=fa[old], w=getW(x);
	if(!isRoot(old))	ch[oldf][ch[oldf][1]==old] = x;
	ch[old][w] = ch[x][w^1]; ch[x][w^1] = old; 
	fa[ch[x][w^1]] = x; fa[ch[old][w]] = old; fa[x] = oldf;
	upd(old); upd(x);
}
void splay(int x){
	xf(x);
	while(!isRoot(x)){
		int f=fa[x];
		if(!isRoot(f))	rotate(getW(x)==getW(f)?f:x);
		rotate(x);
	}
}
void access(int x){
	int y=0;
	while(x){
		splay(x);
		ch[x][1] = y;
		upd(x);
		y = x;
		x = fa[x];
	}
}
void makeRoot(int x){
	access(x);
	splay(x);
	rev[x] ^= 1;
}
int query(int u, int v){
	makeRoot(u);
	access(v);
	splay(v);
	return sum[v];
}
int findRoot(int x){
	access(x);
	splay(x);
	while(ch[x][0])
		x = ch[x][0];
	splay(x);//谜之降低常数
	return x;
}
void link(int u, int v){
	makeRoot(u);
	fa[u] = v;
}
void cut(int u, int v){
	makeRoot(u);
	access(v);
	splay(v);
	if(ch[u][0] || ch[u][1] || fa[u]!=v || ch[v][getW(u)^1])	return ;
	ch[v][0] = fa[u] = 0;
}
void change(int u, int v){
	val[u] = v;
	access(u);
	splay(u);
}
int main(){
	cin>>n>>m;
	for(int i=1; i<=n; i++)
		scanf("%d", &val[i]);
	while(m--){
		scanf("%d %d %d", &opt, &uu, &vv);
		if(opt==0)	printf("%d\n", query(uu, vv));
		else if(opt==1 && findRoot(uu)!=findRoot(vv))
			link(uu, vv);
		else if(opt==2 && findRoot(uu)==findRoot(vv))
			cut(uu, vv);
		else if(opt==3)	change(uu, vv);
	}
	return 0;
}
posted @ 2018-04-11 11:23  poorpool  阅读(110)  评论(0)    收藏  举报