P3690 【模板】Link Cut Tree (动态树)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=2e6+10; int fa[N],val[N],sum[N],son[N][2],rev[N],st[N]; int get(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;} void up(int x){sum[x]=sum[son[x][1]]^sum[son[x][0]]^val[x];} void change(int x){swap(son[x][0],son[x][1]);rev[x]^=1;} void down(int x) { if(!rev[x])return ; rev[x]=0; if(son[x][0])change(son[x][0]); if(son[x][1])change(son[x][1]); } void rotate(int x) { int y=fa[x],z=fa[y],k=son[fa[x]][1]==x,w=son[x][k^1]; if(get(y))son[z][son[z][1]==y]=x;son[x][k^1]=y;son[y][k]=w; if(w)fa[w]=y;fa[y]=x;fa[x]=z; up(y);up(x); } void splay(int x) { int y=x,top=0;st[++top]=y; while(get(y))st[++top]=y=fa[y]; while(top)down(st[top--]); while(get(x)) { int y=fa[x],z=fa[y]; if(get(y)) rotate((son[y][0]==x)^(son[z][0]==y)?x:y); rotate(x); }up(x); } void access(int x) { for(int y=0;x;x=fa[y=x]) splay(x),son[x][1]=y,up(x); } void makeroot(int x) { access(x);splay(x);change(x); } int findroot(int x) { access(x);splay(x); while(son[x][0])down(x),x=son[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) { split(x,y); if(findroot(y)==x&&fa[y]==x&&!son[y][0]) fa[y]=son[x][1]=0,up(x); }int n,m,x,y,op; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&val[i]); while(m--) { scanf("%d%d%d",&op,&x,&y); if(op==0)split(x,y),printf("%d\n",sum[y]); if(op==1)link(x,y); if(op==2)cut(x,y); if(op==3)splay(x),val[x]=y;//这里不up也没事 反正问的时候也会up } return 0; }
P2147 [SDOI2008]洞穴勘测
题意: 就是可删除的并查集
题解: 没啥好说的 比模板简单
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) //////////////////////////////////// const int N=2e6+10; int fa[N],son[N][2],rev[N],st[N]; int get(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;} void change(int x){swap(son[x][1],son[x][0]);rev[x]^=1;} void down(int x) { if(!rev[x])return ; rev[x]=0; if(son[x][1])change(son[x][1]); if(son[x][0])change(son[x][0]); } void rotate(int x) { int y=fa[x],z=fa[y],k=son[fa[x]][1]==x,w=son[x][k^1]; if(get(y))son[z][son[z][1]==y]=x;son[x][k^1]=y;son[y][k]=w; if(w)fa[w]=y;fa[y]=x;fa[x]=z; } void splay(int x) { int y=x,top=0;st[++top]=y; while(get(y))st[++top]=y=fa[y]; while(top)down(st[top--]); while(get(x)) { int y=fa[x],z=fa[y]; if(get(y)) rotate((son[y][0]==x)^(son[z][0]==y)?x:y); rotate(x); } } void access(int x) { for(int y=0;x;x=fa[y=x]) splay(x),son[x][1]=y; } void makeroot(int x) { access(x);splay(x);change(x); } int findroot(int x) { access(x);splay(x); while(son[x][0])down(x),x=son[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; } bool judge(int x,int y) { makeroot(x); return findroot(y)==x; } void cut(int x,int y) { split(x,y); if(findroot(y)==x&&fa[y]==x&&!son[y][0]) fa[y]=son[x][1]=0; }char s[100];int n,m,x,y; int main() { scanf("%d%d",&n,&m); while(m--) { scanf("%s %d%d",s,&x,&y); if(s[0]=='Q')printf("%s\n",judge(x,y)?"Yes":"No"); if(s[0]=='C')link(x,y); if(s[0]=='D')cut(x,y); } return 0; }