- 和可持久化数组及其类似,用主席树只是利用了主席树的结构
- 主席树的叶子节点存的是该节点的爸爸
- 由于每次修改的数量不能太多(不然会RE+TLE),所以不能路径压缩,只能按秩合并
#include<cstdio>
using namespace std;
const int N=2e5+5,M=3e6+5;;
struct A{ int fa,r; }c[M];
int n,m,r[N],ls[M],rs[M],rt[N],cnt;
inline int read()
{
int ret=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
{
ret=(ret<<1)+(ret<<3)+ch-'0';
ch=getchar();
}
return ret;
}
void build(int &p,int l,int r)
{
p=++cnt;
if(l==r)
{
c[p]=(A){l,0};
return;
}
int mid=l+r>>1;
build(ls[p],l,mid);
build(rs[p],mid+1,r);
}
A get(int p,int l,int r,int x)
{
if(l==r)
return (A){c[p].fa,c[p].r};
int mid=l+r>>1;
if(x<=mid)
return get(ls[p],l,mid,x);
else
return get(rs[p],mid+1,r,x);
}
void update(int p1,int &p2,int l,int r,int x,A y)
{
p2=++cnt;
if(l==r)
{
c[p2]=y;
return;
}
int mid=l+r>>1;
ls[p2]=ls[p1];
rs[p2]=rs[p1];
if(x<=mid)
update(ls[p1],ls[p2],l,mid,x,y);
else
update(rs[p1],rs[p2],mid+1,r,x,y);
}
A find(int root,int u)
{
A x=get(root,1,n,u);
return u==x.fa?x:find(root,x.fa);
}
int main()
{
n=read(),m=read();
build(rt[0],1,n);
for(int i=1;i<=m; i++)
{
int op=read();
if(op==1)
{
int x=read(),y=read();
rt[i]=rt[i-1];
A u=find(rt[i],x),v=find(rt[i],y);
if(u.fa!=v.fa)
{
if(u.r>v.r)
update(rt[i-1],rt[i],1,n,v.fa,(A){u.fa,v.r});
else
if(u.r==v.r)
{
update(rt[i-1],rt[i],1,n,u.fa,(A){v.fa,u.r});
update(rt[i],rt[i],1,n,v.fa,(A){v.fa,v.r+1});
}
else
update(rt[i-1],rt[i],1,n,u.fa,(A){v.fa,u.r});
}
} else
if(op==2)
{
int k=read();
rt[i]=rt[k];
}else
{
rt[i]=rt[i-1];
int a=read(),b=read();
A u=find(rt[i],a),v=find(rt[i],b);
putchar((u.fa==v.fa)+48);
puts("");
}
}
return 0;
}