【洛谷 P3690】 【模板】Link Cut Tree (动态树)

题目链接
(RT)
FlashHu巨佬的博客

#include <cstdio>
#define R register int
#define I inline void
#define lc c[x][0]
#define rc c[x][1]
const int MAXN = 300010;
inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
    return s * w;
}
int f[MAXN], c[MAXN][2], v[MAXN], s[MAXN], st[MAXN], tag[MAXN];
inline int nroot(R x){
	return c[f[x]][0] == x || c[f[x]][1] == x;
}
I pushup(R x){
	s[x] = s[lc] ^ s[rc] ^ v[x];
}
I swap(R x){
	lc ^= rc; rc = lc ^ rc; lc ^= rc; tag[x] ^= 1;
}
I pushdown(R x){
	if(tag[x]){
		swap(lc); swap(rc);
		tag[x] = 0;
	}
}
I rotate(R x){
	R y = f[x], z = f[y], k = c[y][1] == x, w = c[x][!k];
	if(nroot(y)) c[z][c[z][1] == y] = x;
	c[x][!k] = y; c[y][k] = w; f[y] = x; f[x] = z;
	if(w) f[w] = y;
	pushup(y);
}
I splay(R x){
	R y = x, z = 0;
	st[++z] = y;
	while(nroot(y)) st[++z] = y = f[y];
	while(z) pushdown(st[z--]);
	while(nroot(x)){
		y = f[x]; z = f[y];
		if(nroot(y)) (c[z][1] == y) ^ (c[y][1] == x) ? rotate(x) : rotate(y);
		rotate(x);
	}
	pushup(x);
}
I access(R x){
	for(R y = 0; x; x = f[y = x]){
	   splay(x); rc = y; pushup(x);
    }
}
I makeroot(R x){
	access(x); splay(x); 
	swap(x);
}
inline int findroot(R x){
	makeroot(x); splay(x);
	while(lc){ x = lc; pushdown(x); }
	splay(x);
	return x;
}
I split(R x, R y){
	makeroot(x); access(y); splay(y);
}
I link(R x, R y){
	makeroot(x);
	if(findroot(y) != x) f[x] = y;
}
I cut(R x, R y){
	split(x, y);
	if(c[y][0] == x){
	   f[x] = c[y][0] = 0;
	   pushup(y);
    }
}
int n, m, opt, a, b;
int main(){
	n = read(); m = read();
	for(R i = 1; i <= n; ++i)
	   v[i] = read();
	while(m--){
		opt = read(); a = read(); b = read();
		switch(opt){
			case 0 : split(a, b); printf("%d
", s[b]); break;
			case 1 : link(a, b); break;
			case 2 : cut(a, b); break;
			case 3 : splay(a); v[a] = b; break;
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Qihoo360/p/10331209.html