<题意概括>
一道可持久化并查集的裸题
<做法>
类似于普通并查集
只不过普通并查集用普通数组实现
而可持久化并查集用可持久化数组实现
<Code>
此处给出递归和迭代两种写法
<Recursive>
#include<cstdio> #define Fast register inline char Getchar(){ static char BUF[16384],*S=BUF,*T=BUF; return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++; } inline int Getint(){ Fast int s=0;Fast char c=Getchar(),w=0; while(c<48||c>57)c==45&&(w=1),c=Getchar(); while(c>47&&c<58)s=s*10+c-48,c=Getchar(); return w?-s:s; } struct Node{ int key; Node *lson,*rson; Node(int key=0):key(key){} Node(Node*&o):key(o->key),lson(o->lson),rson(o->rson){} }*root[20001]; #define ls(o) (o)->lson #define rs(o) (o)->rson inline void Build(Node*&o,const int&L,const int&R,const int*Arr){ o=new Node; if(L==R){o->key=Arr[L];return;} Fast int Mid=(L+R)>>1; Build(ls(o),L,Mid,Arr); Build(rs(o),Mid+1,R,Arr); } inline void Modify(Node*&PostVersion,Node*&NewVersion,const int&L,const int&R,const int&Loc,const int&key){ NewVersion=new Node(PostVersion); if(L==R){NewVersion->key=key;return;} Fast int Mid=(L+R)>>1; if(Loc<=Mid)Modify(ls(PostVersion),ls(NewVersion),L,Mid,Loc,key); else Modify(rs(PostVersion),rs(NewVersion),Mid+1,R,Loc,key); } inline int Query(Node*&o,const int&L,const int&R,int&k){ if(L==R)return o->key; Fast int Mid=(L+R)>>1; if(k>Mid)return Query(rs(o),Mid+1,R,k); return Query(ls(o),L,Mid,k); } int uset[20001]; int N; inline int Find(Node*&Version,int Loc){ Fast int Fa; while((Fa=Query(Version,1,N,Loc))!=Loc)Loc=Fa; return Loc; } #define UnionSet(PostVersion,NewVersion,x,y) Modify(PostVersion,NewVersion,1,N,Find(PostVersion,x),Find(PostVersion,y)) #define SameSet(Version,x,y) (Find(Version,x)==Find(Version,y)) int main(){ N=Getint(); Fast int M=Getint(),opt,A,B; for(Fast int i=1;i<=N;++i)uset[i]=i; Build(*root,1,N,uset); for(Fast int i=1;i<=M;++i){ opt=Getint(),A=Getint(); if(opt==1)UnionSet(root[i-1],root[i],A,Getint()); else if(opt==2)root[i]=root[A]; else B=Getint(),putchar(SameSet(root[i]=root[i-1],A,B)?49:48),putchar(10); } }
<Iterative>
#include<cstdio> #define Fast register inline char Getchar(){ static char BUF[16384],*S=BUF,*T=BUF; return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++; } inline int Getint(){ Fast int s=0;Fast char c=Getchar(),w=0; while(c<48||c>57)c==45&&(w=1),c=Getchar(); while(c>47&&c<58)s=s*10+c-48,c=Getchar(); return w?-s:s; } struct Node{ int key; Node *lson,*rson; Node(int key=0):key(key){} Node(Node*&o):key(o->key),lson(o->lson),rson(o->rson){} }*root[20001]; #define ls(o) (o)->lson #define rs(o) (o)->rson inline void Build(Node*&o,const int&L,const int&R,const int*Arr){ o=new Node; if(L==R){o->key=Arr[L];return;} Fast int Mid=(L+R)>>1; Build(ls(o),L,Mid,Arr); Build(rs(o),Mid+1,R,Arr); } inline void Modify(Node*&PostVersion,Node*&NewVersion,int L,int R,const int&Loc,const int&key){ Fast Node**Post=&PostVersion,**New=&NewVersion; Fast int Mid; while(L!=R){ Mid=(L+R)>>1; *New=new Node(*Post); if(Loc<=Mid)Post=&(ls(*Post)),New=&(ls(*New)),R=Mid; else Post=&(rs(*Post)),New=&(rs(*New)),L=Mid+1; } *New=new Node(*Post); (*New)->key=key; } inline int Query(Node*Version,int L,int R,const int&k){ Fast int Mid; while(L!=R){ Mid=(L+R)>>1; if(k<=Mid)Version=ls(Version),R=Mid; else Version=rs(Version),L=Mid+1; } return Version->key; } int uset[20001]; int N; inline int Find(Node*&Version,int Loc){ Fast int Fa; while((Fa=Query(Version,1,N,Loc))!=Loc)Loc=Fa; return Loc; } #define UnionSet(PostVersion,NewVersion,x,y) Modify(PostVersion,NewVersion,1,N,Find(PostVersion,x),Find(PostVersion,y)) #define SameSet(Version,x,y) (Find(Version,x)==Find(Version,y)) int main(){ N=Getint(); Fast int M=Getint(),opt,A,B; for(Fast int i=1;i<=N;++i)uset[i]=i; Build(*root,1,N,uset); for(Fast int i=1;i<=M;++i){ opt=Getint(),A=Getint(); if(opt==1)UnionSet(root[i-1],root[i],A,Getint()); else if(opt==2)root[i]=root[A]; else B=Getint(),putchar(SameSet(root[i]=root[i-1],A,B)?49:48),putchar(10); } }