LCT模板坑点总结

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=100005;
int n,m;
struct LCT {
	int fa[MAXN],val[MAXN],rev[MAXN],ch[MAXN][2],sum[MAXN],tot;
	int stk[MAXN],tp;
	void up(int x) {
		sum[x]=sum[ch[x][0]]^sum[ch[x][1]]^val[x];
	}
	void push_rev(int x) {
		rev[x]^=1;
		swap(ch[x][0],ch[x][1]);
	}
	void down(int x) {
		if(rev[x]) {
			rev[x]=0; 
			push_rev(ch[x][0]);
			push_rev(ch[x][1]);
		}
	}
	int get(int x) {
		return ch[fa[x]][1]==x;
	}
	bool isroot(int x) {
		return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
	}
	void rotate(int x) {
		int f1=fa[x],f2=fa[f1],id=get(x);
		ch[f1][id]=ch[x][id^1]; fa[ch[f1][id]]=f1;
		if(!isroot(f1)) ch[f2][get(f1)]=x; fa[x]=f2; //!!!!!
		ch[x][id^1]=f1; fa[f1]=x;
		up(f1);
	}
	void splay(int x) {
		tp=0;
		int y=x;
		stk[++tp]=y; //!!!!!
		while(!isroot(y)) stk[++tp]=y=fa[y];
		while(tp) down(stk[tp--]);
		while(!isroot(x)) { //!!!!!
			int f1=fa[x],f2=fa[f1];
			if(!isroot(f1)) {
				if(get(x)==get(f1)) rotate(f1);
				else rotate(x);
			}
			rotate(x);
		}
		up(x);
	}
	void access(int x) {
		for(int y=0;x;y=x,x=fa[x])
			splay(x),ch[x][1]=y,up(x);
	}
	void makeroot(int x) {
		access(x);
		splay(x);
		push_rev(x);
	}
	int findroot(int x) {
		access(x); splay(x);
		while(ch[x][0]) x=ch[x][0];
		splay(x);
		return x;
	}
	void split(int x,int y) {
		makeroot(x);
		access(y);
		splay(y);
	}
	void link(int x,int y) {
		makeroot(x);
		if(findroot(y)!=x) fa[x]=y;
	}
	void cut(int x,int y) {
		makeroot(x);
		if(findroot(y)==x&&fa[y]==x&&!ch[y][0]) { //!!!!!
			fa[y]=ch[x][1]=0;
			up(x);
		}
	}
}tr;
int main() {
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&tr.val[i]);
	for(int i=1;i<=m;i++) {
		int opt,x,y;
		scanf("%d%d%d",&opt,&x,&y);
		switch(opt) {
			case 0: tr.split(x,y); printf("%d
",tr.sum[y]); break;
			case 1:	tr.link(x,y); break;
			case 2:	tr.cut(x,y); break;
			case 3:	tr.makeroot(x); tr.val[x]=y; tr.up(x); break;
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Gkeng/p/12003058.html