可持久化并查集
可持久化就用主席树实现,学习自这篇博客
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define N 4000005 using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } int ndnum,n; int fa[N],lc[N],rc[N],dep[N],root[N]; void build(int k,int l,int r)//维护的是fa { if(l==r){fa[k]=l;return;} int mid=(l+r)>>1; build(lc[k]=++ndnum,l,mid); build(rc[k]=++ndnum,mid+1,r); } int query(int k,int L,int R,int pos) { if(L==R) return k; int mid=(L+R)>>1; if(pos<=mid)return query(lc[k],L,mid,pos); else return query(rc[k],mid+1,R,pos); } int get(int k,int x) { int now=query(k,1,n,x); if(fa[now]==x)return now; return get(k,fa[now]); } void merge(int last,int &k,int L,int R,int pos,int f) { k=++ndnum;lc[k]=lc[last];rc[k]=rc[last];//复制 if(L==R) { fa[k]=f; dep[k]=dep[last]; return; } int mid=(L+R)>>1; if(pos<=mid)merge(lc[last],lc[k],L,mid,pos,f); else merge(rc[last],rc[k],mid+1,R,pos,f); } void update(int k,int L,int R,int pos) { if(L==R){dep[k]++;return;} int mid=(L+R)>>1; if(pos<=mid)update(lc[k],L,mid,pos); else update(rc[k],mid+1,R,pos); } int main() { n=read();int m=read(); build(root[0],1,n); for(int i=1;i<=m;++i) { int op=read(); if(op==1) { int a=read(),b=read(); root[i]=root[i-1]; int posx=get(root[i],a); int posy=get(root[i],b); if(fa[posx]==fa[posy])continue; if(dep[posx]>dep[posy])swap(posx,posy); merge(root[i-1],root[i],1,n,fa[posx],fa[posy]); if(dep[posx]==dep[posy])update(root[i],1,n,fa[posy]); //因为不可能出现深度相同的两个点,所以要把其中一个点深度+1,由于是深度小的合到深度大的上,所以把深度小的增加深度 } else if(op==2) { int x=read(); root[i]=root[x]; } else { int a=read(),b=read(); root[i]=root[i-1]; int posx=get(root[i],a); int posy=get(root[i],b); if(fa[posx]==fa[posy])printf("1\n"); else printf("0\n"); } } }