【BZOJ 3282】Tree Link Cut Tree模板题

知道了为什么要换根(changeroot),access后为什么有时要splay,以及LCT的其他操作,算是比较全面的啦吧,,,

现在才知道这些,,,真心弱,,,

#include<cstdio>
#include<algorithm>
#define read(x) x=getint()
using namespace std;
const int N=300003;
inline int getint(){char c;int ret=0;for(c=getchar();c<'0'||c>'9';c=getchar());for(;c>='0'&&c<='9';c=getchar())ret=ret*10+c-'0';return ret;}
struct node *null;
struct node{
	node();
	node *fa,*ch[2];
	int d,rev,w;
	void push() {if(rev) {ch[0]->rev^=1; ch[1]->rev^=1; rev=0; swap(ch[0],ch[1]);}}
	void count() {w=ch[0]->w^ch[1]->w^d;}
	void setc(node *r,bool c) {ch[c]=r; r->fa=this;}
	bool check() {return fa==null||((fa->ch[0]!=this)&&(fa->ch[1]!=this));}
	bool pl() {return fa->ch[1]==this;}
}*T[N];
node::node() {d=rev=w=0; fa=ch[0]=ch[1]=null;}
int n;
inline void Build() {null=new node; *null=node();}
inline void rotate(node *r){
	node *f=r->fa;
	bool c=r->pl();
	if (!f->check()) f->fa->setc(r,f->pl());
	else r->fa=f->fa;
	f->setc(r->ch[!c],c); r->setc(f,!c);
	f->count();
}
inline void update(node *r) {if (!r->check()) update(r->fa); r->push();}
inline void splay(node *r){
	update(r);
	for(;!r->check();rotate(r))
		if (!r->fa->check()) rotate(r->fa->pl()==r->pl()?r->fa:r);
	r->count();
}
inline node *access(node *r){
	node *y=null;
	for(;r!=null;y=r,r=r->fa){
		splay(r);
		r->setc(y,1);
		r->count();
	}
	return y;
}
inline void changeroot(node *r) {access(r)->rev^=1; splay(r);}
inline void cut(node *r,node *y) {changeroot(r); access(y); splay(y); y->ch[0]->fa=null; y->ch[0]=null;}
inline void link(node *r,node *y) {changeroot(r); r->fa=y;}
inline node *findroot(node *r) {access(r); splay(r); while(r->ch[0]!=null) r=r->ch[0]; return r;}
int main(){
	Build();
	read(n); int x,q,a,b; read(q);
	for(int i=1;i<=n;i++) {T[i]=new node; read(T[i]->d); T[i]->w=T[i]->d;}
	while (q--){
		read(x); read(a); read(b);
		switch (x){
			case 0:
				changeroot(T[a]); access(T[b]); splay(T[b]); printf("%d
",T[b]->w);
			break;
			case 1:
				if (findroot(T[a])!=findroot(T[b])) link(T[a],T[b]);
			break;
			case 2:
				if (findroot(T[a])==findroot(T[b])) cut(T[a],T[b]);
			break;
			case 3:
				changeroot(T[a]); T[a]->d=b; T[a]->count();
			break;
		}
	}
	return 0;
}

这样就行啦

原文地址:https://www.cnblogs.com/abclzr/p/5267290.html