思路:
用主席树维护并查集森林,每次连接时新增结点。
似乎并不需要启发式合并,我随随便便写了一个就跑到了3674第一页?
3673是这题的弱化版,本来写个暴力就能过,现在借用加强版的代码(去掉异或),直接吊打暴力程序。
1 #include<cstdio> 2 #include<cctype> 3 inline int getint() { 4 register char ch; 5 while(!isdigit(ch=getchar())); 6 register int x=ch^'0'; 7 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 8 return x; 9 } 10 const int N=200001,SIZE=3850000; 11 class PresistentDisjointSet { 12 private: 13 unsigned int left[SIZE],right[SIZE],sz; 14 int anc[SIZE]; 15 unsigned int newnode() { 16 return sz++; 17 } 18 unsigned int getpos(const unsigned int p,const int b,const int e,const int x) { 19 if(b==e) return p; 20 int mid=(b+e)>>1; 21 return (x<=mid)?getpos(left[p],b,mid,x):getpos(right[p],mid+1,e,x); 22 } 23 public: 24 unsigned int root[N]; 25 PresistentDisjointSet() { 26 sz=0; 27 } 28 void Build(unsigned int &p,const int b,const int e) { 29 p=newnode(); 30 if(b==e) { 31 anc[p]=b; 32 return; 33 } 34 int mid=(b+e)>>1; 35 Build(left[p],b,mid); 36 Build(right[p],mid+1,e); 37 } 38 unsigned int find(const unsigned int p,const int b,const int e,const int x) { 39 int q=getpos(p,b,e,x); 40 return x==anc[q]?q:find(p,b,e,anc[q]); 41 } 42 unsigned int Union2(const unsigned int p,const int b,const int e,const int x,const int y) { 43 unsigned int new_p=newnode(); 44 if(b==e) { 45 anc[new_p]=y; 46 return new_p; 47 } 48 int mid=(b+e)>>1; 49 if(x<=mid) left[new_p]=Union2(left[p],b,mid,x,y),right[new_p]=right[p]; 50 if(x>mid) right[new_p]=Union2(right[p],mid+1,e,x,y),left[new_p]=left[p]; 51 return new_p; 52 } 53 bool isConnected(const int x,const int y) { 54 return anc[x]==anc[y]; 55 } 56 unsigned int Union(const unsigned int p,const int b,const int e,int x,int y) { 57 x=find(p,b,e,x),y=find(p,b,e,y); 58 if(isConnected(x,y)) return p; 59 return Union2(p,b,e,anc[x],anc[y]); 60 } 61 }; 62 PresistentDisjointSet s; 63 int main() { 64 int n=getint(),lastans=0; 65 s.Build(s.root[0],1,n); 66 int m=getint(); 67 for(register int i=1;i<=m;i++) { 68 int op=getint(); 69 if(op==1) s.root[i]=s.Union(s.root[i-1],1,n,getint()^lastans,getint()^lastans); 70 else if(op==2) s.root[i]=s.root[getint()^lastans]; 71 else s.root[i]=s.root[i-1],printf("%d ",lastans=s.isConnected(s.find(s.root[i],1,n,getint()^lastans),s.find(s.root[i],1,n,getint()^lastans))); 72 } 73 return 0; 74 }