用可持久化线段树维护可持久化数组。
按秩合并和按size合并都是把小的合到大的上。
贴一个路径压缩+按秩合并的吧(跑得最慢)
#include <bits/stdc++.h>
using namespace std;
#define N 210000
#define M 10000000
#define ls l,mid,ch[now][0]
#define rs mid+1,r,ch[now][1]
int n,m,now;
struct array
{
int root[N],ch[M][2],val[M],cnt;
void build(int l,int r,int &now,int tp)
{
now=++cnt;
if(l==r){val[now]=tp ? 0:l;return;}
int mid=(l+r)>>1;
build(ls,tp);build(rs,tp);
}
void insert(int l,int r,int &now,int pos,int v)
{
int t=now;now=++cnt;
if(l==r){val[now]=v;return;}
int mid=(l+r)>>1;
ch[now][0]=ch[t][0];
ch[now][1]=ch[t][1];
if(mid>=pos)insert(ls,pos,v);
else insert(rs,pos,v);
}
void mdf(int x,int y)
{insert(1,n,root[now],x,y);}
int query(int l,int r,int now,int pos)
{
if(l==r)return val[now];
int mid=(l+r)>>1;
if(mid>=pos)return query(ls,pos);
else return query(rs,pos);
}
int g(int x){return query(1,n,root[now],x);}
}size,fa;
int find(int x)
{
int t=fa.g(x);
if(t==x)return x;
t=find(t);fa.mdf(x,t);
return t;
}
int main()
{
//freopen("tt.in","r",stdin);
scanf("%d%d",&n,&m);
fa.build(1,n,fa.root[0],0);
size.build(1,n,size.root[0],1);
for(int i=1,tp,a,b;i<=m;i++)
{
scanf("%d",&tp);
now=i;
size.root[i]=size.root[i-1];
fa.root[i]=fa.root[i-1];
if(tp==1)
{
scanf("%d%d",&a,&b);
int x=find(a),y=find(b);
int sx=size.g(x),sy=size.g(y);
if(x==y)continue;
if(sx>sy)swap(x,y),swap(sx,sy);
if(sx==sy)size.mdf(y,sy+1);
fa.mdf(x,y);
}
if(tp==2)
{
scanf("%d",&a);
size.root[i]=size.root[a];
fa.root[i]=fa.root[a];
}
if(tp==3)
{
scanf("%d%d",&a,&b);
printf("%d\n",find(a)==find(b));
}
}
return 0;
}