题目描述
n个集合 m个操作
操作:
-
1 a b
合并a,b所在集合 -
2 k
回到第k次操作之后的状态(查询算作操作) -
3 a b
询问a,b是否属于同一集合,是则输出1否则输出0
输入格式
无
输出格式
无
输入输出样例
输入 #1复制
5 6 1 1 2 3 1 2 2 0 3 1 2 2 1 3 1 2
输出 #1复制
View Code
1 0 1
主席树维护即可 注意启发式合并
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; // const int N=2e6+10; int T[N],t[N<<5],lson[N<<5],rson[N<<5],dep[N<<5],n,m,op,a,b,c,ncnt; void build(int l,int r,int &pos) { pos=++ncnt; if(l==r){t[pos]=l;return ;} int m=(l+r)>>1; build(l,m,lson[pos]); build(m+1,r,rson[pos]); } void upnode(int x,int fa,int l,int r,int pre,int &pos) { pos=++ncnt;t[pos]=t[pre];lson[pos]=lson[pre];rson[pos]=rson[pre]; if(l==r){t[pos]=fa;dep[pos]=dep[pre];return ;} int m=(l+r)>>1; if(x<=m)upnode(x,fa,l,m,lson[pos],lson[pos]); else upnode(x,fa,m+1,r,rson[pos],rson[pos]); } int qsum(int x,int l,int r,int pos) { if(l==r)return pos; int m=(l+r)>>1; if(x<=m)return qsum(x,l,m,lson[pos]); else return qsum(x,m+1,r,rson[pos]); } void adddep(int x,int l,int r,int pos) { if(l==r){dep[pos]++;return ;} int m=(l+r)>>1; if(x<=m)adddep(x,l,m,lson[pos]); else adddep(x,m+1,r,rson[pos]); } int find1(int x,int tt) { int pos=qsum(x,1,n,tt); if(t[pos]==x)return pos; return find1(t[pos],tt); } int main() { cin>>n>>m; build(1,n,T[0]); rep(i,1,m) { cin>>op; if(op==1) { cin>>a>>b; T[i]=T[i-1]; int x=find1(a,T[i]),y=find1(b,T[i]); if(t[x]==t[y])continue; if(dep[x]>dep[y])swap(x,y); upnode(t[x],t[y],1,n,T[i-1],T[i]); if(dep[x]==dep[y])adddep(y,1,n,T[i]); } else if(op==2) { int k;cin>>k; T[i]=T[k]; } else { T[i]=T[i-1]; cin>>a>>b; if( t[find1(a,T[i])]==t[find1(b,T[i])] ) printf("1\n"); else printf("0\n"); } } return 0; }