可持久化就用主席树实现,学习自这篇博客

#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");
}
}
}
