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

版权声明:欢迎转载!请注明出处!qwq https://blog.csdn.net/g21glf/article/details/86595212

传送门

【题目分析】

emmm,先留个坑。

板子先留着。

Link和Cut的时候好神奇啊qwq。

看懂再写点。qwq

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+10;

int n,q;
int lc[MAXN],rc[MAXN],val[MAXN];
int fa[MAXN],sum[MAXN];
int rev[MAXN];
int que[MAXN],tot;

int Read(){
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

void push_up(int root){
	sum[root]=sum[lc[root]]^sum[rc[root]]^val[root];
}

void push_down(int root){
	if(rev[root]){
		int lson=lc[root],rson=rc[root];
		rev[lson]^=1,rev[rson]^=1;
		rev[root]^=1;
		swap(lc[root],rc[root]);
	}
}

int isroot(int x){
	return lc[fa[x]]!=x&&rc[fa[x]]!=x;
}

int which(int x,int y){
	return rc[y]==x;
}

void rotate(int x){
	int y=fa[x],z=fa[y];
	if(!isroot(y)){
		if(!which(y,z))
		  lc[z]=x;
		else
		  rc[z]=x;
	}
	if(!which(x,y)){
		fa[x]=z,fa[y]=x;
		fa[rc[x]]=y;
		lc[y]=rc[x];
		rc[x]=y;
	}
	else{
		fa[x]=z,fa[y]=x;
		fa[lc[x]]=y;
		rc[y]=lc[x];
		lc[x]=y;
	}
	push_up(y),push_up(x);
}

void splay(int x){
	tot=0;
	que[++tot]=x;
	for(int i=x;!isroot(i);i=fa[i])
	  que[++tot]=fa[i];
	for(int i=tot;i;--i)
	  push_down(que[i]);
	while(!isroot(x)){
		int y=fa[x],z=fa[y];
		if(!isroot(y)){
			if((!which(x,y))^(!which(y,z)))
			  rotate(x);
			else
			  rotate(y);
		}
		rotate(x);
	}
}

void access(int x){
	for(int t=0;x;t=x,x=fa[x]){
		splay(x);
		rc[x]=t;
		push_up(x);
	}
}

void makeroot(int x){
	access(x);
	splay(x);
	rev[x]^=1;
}

int findroot(int x){
	access(x);
	splay(x);
	while(lc[x]){
		push_down(x);
		x=lc[x];
	}
	return x;
}

void link(int x,int y){
	makeroot(x);
	if(findroot(y)!=x)
	  fa[x]=y;
}

void cut(int x,int y){
	splay(y);
	lc[y]=fa[x]=0;
	push_up(y);
}

int main(){
	n=Read(),q=Read();
	for(int i=1;i<=n;++i){
		val[i]=Read();
		sum[i]=val[i];
	}
	while(q--){
		int cz=Read();
		if(cz==0){
			int x=Read(),y=Read();
			makeroot(x);
			access(y);
			splay(y);
			cout<<sum[y]<<'\n';
		}
		if(cz==1){
			int x=Read(),y=Read();
			int fx=findroot(x),fy=findroot(y);
			if(fx!=fy)
			  link(x,y);
		}
		if(cz==2){
			int x=Read(),y=Read();
			if(findroot(x)!=findroot(y))
			  continue;
			makeroot(x);
			access(y);
			if(!rc[lc[y]]&&!lc[lc[y]])
			  cut(x,y);
		}
		if(cz==3){
			int x=Read(),k=Read();
			access(x);
			splay(x);
			val[x]=k;
			push_up(x);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/86595212
今日推荐