//并查集-都要给fa赋初值!!
//======================================
/*递归版路径压缩*/
int fa[maxn]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void merge(int x,int y) { fa[find(x)]=find(y); }
//======================================
/*循环版路径压缩,循环稍快一点*/
int fa[maxn]; int find(int x) { while(x!=fa[x]) x=fa[x]=fa[fa[x]]; return x; } void merge(int x,int y) { fa[find(x)]=find(y); }
//======================================
/*按秩合并*/
/*把深度小的并到深度大的上,保证深度不会增加*/
int fa[maxn],rank[maxn]; int find(int x) { return fa[x]==0?x:find(fa[x]); } void merge(int x,int y) { x=find(x); y=find(y); if(x!=y) { if(rank[x]<=rank[y])fa[x]=y,rank[y]=max(rank[y],rank[x]+1); else fa[y]=x,rank[x]=max(rank[x],rank[y]+1); } }
//======================================
//可持久化并查集
/*每个版本并查集的深度不同,需要开可持久化数组记录每个版本的dep
两个可持久化数组分别维护fa和dep
注意优化要选择按秩合并,不要路径压缩
1,合并a,b
2,回到第k个版本
3,询问a,b是不是在一个集合里
每次操作都算作一个版本*/
#include <bits/stdc++.h> using namespace std; #define ll long long #define lowbit(a) ((a)&-(a)) #define clean(a,b) memset(a,b,sizeof(a)) const int mod = 1e9 + 7; const int inf=0x3f3f3f3f; int _; //================================================================== const int maxn = 2e5+9; int tot,cnt,rootfa[maxn],rootdep[maxn],n; struct node { int l,r,val; }hjt[maxn*40*2]; void build(int l,int r,int &now) { now=++cnt; if(l==r) { hjt[now].val=++tot; return ; } int mid=(l+r)>>1; build(l,mid,hjt[now].l); build(mid+1,r,hjt[now].r); } void modify(int l,int r,int var,int &now,int pos,int num) { now=++cnt; hjt[now]=hjt[var]; if(l==r) { hjt[now].val=num; return ; } int mid=(l+r)>>1; if(pos<=mid) modify(l,mid,hjt[var].l,hjt[now].l,pos,num); else modify(mid+1,r,hjt[var].r,hjt[now].r,pos,num); } int query(int l,int r,int now,int pos) { if(l==r) return hjt[now].val; int mid=(l+r)>>1; if(pos<=mid) return query(l,mid,hjt[now].l,pos); else return query(mid+1,r,hjt[now].r,pos); } int find(int var,int x) { int fx=query(1,n,rootfa[var],x); return fx==x?x:find(var,fx); } void merge (int var,int x,int y) { x=find(var-1,x); y=find(var-1,y); if(x==y) { rootfa[var]=rootfa[var-1]; rootdep[var]=rootfa[var-1]; } else { int dpx=query(1,n,rootdep[var-1],x); int dpy=query(1,n,rootdep[var-1],y); if(dpx<dpy) { modify(1,n,rootfa[var-1],rootfa[var],x,y); rootdep[var]=rootdep[var-1]; } else if(dpx>dpy) { modify(1,n,rootfa[var-1],rootfa[var],y,x); rootdep[var]=rootdep[var-1]; } else { modify(1,n,rootfa[var-1],rootfa[var],x,y); modify(1,n,rootdep[var-1],rootdep[var],y,dpy+1); } } } //================================================================== int main() { int m,a,b,k,op; scanf("%d%d",&n,&m); build(1,n,rootfa[0]); for(int var=1;var<=m;var++) { scanf("%d",&op); if(op==1) { scanf("%d%d",&a,&b); merge(var,a,b); } else if(op==2) { scanf("%d",&k); rootfa[var]=rootfa[k]; rootdep[var]=rootdep[k]; } else { scanf("%d%d",&a,&b); rootfa[var]=rootfa[var-1]; rootdep[var]=rootdep[var-1]; int x=find(var,a); int y=find(var,b); if(x==y) puts("1"); else puts("0"); } } return 0; }