1. 程式人生 > >解題:洛谷3402 可持久化並查集

解題:洛谷3402 可持久化並查集

題面

滾下去補學考之前更一發

基於可持久化線段樹實現(我不很喜歡“主席樹”這個名字),注意不能路徑壓縮,首先這與可持久化的思想衝突(即儘量利用之前已有的部分,只修改有修改的部分,路徑壓縮壓完了豈不是gg),其次每次壓縮還會有一個log的時間複雜度(查詢),然後複雜度就是$O(n\log n)$的

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=100005;
 6 struct a
7 { 8 int bel,pst,siz; 9 }aset[N*44]; 10 int root[N],son[N*44][2]; 11 int n,m,t1,t2,t3,tot,ans; 12 int Create(int l,int r) 13 { 14 int nde=++tot; 15 if(l==r) 16 aset[nde]=(a){l,l,1}; 17 else 18 { 19 int mid=(l+r)/2; 20 son[nde][0]=Create(l,mid); 21 son[nde][1
]=Create(mid+1,r); 22 } 23 return nde; 24 } 25 int Insert(int pre,int l,int r,int pos,a task) 26 { 27 int nde=++tot; 28 son[nde][0]=son[pre][0]; 29 son[nde][1]=son[pre][1]; 30 if(l<r) 31 { 32 int mid=(l+r)/2; 33 if(pos<=mid) 34 son[nde][0]=Insert(son[pre][0
],l,mid,pos,task); 35 else 36 son[nde][1]=Insert(son[pre][1],mid+1,r,pos,task); 37 } 38 else aset[nde]=task; 39 return nde; 40 } 41 a Query(int nde,int l,int r,int pos) 42 { 43 if(l==r) 44 return aset[nde]; 45 else 46 { 47 int mid=(l+r)/2; 48 if(pos<=mid) return Query(son[nde][0],l,mid,pos); 49 else return Query(son[nde][1],mid+1,r,pos); 50 } 51 } 52 int finda(int b,int x) 53 { 54 int f=Query(b,1,n,x).bel; 55 return (f==x)?x:finda(b,f); 56 } 57 int main() 58 { 59 scanf("%d%d",&n,&m); 60 root[0]=Create(1,n); 61 for(int i=1;i<=m;i++) 62 { 63 scanf("%d%d",&t1,&t2); 64 if(t1==1) 65 { 66 scanf("%d",&t3); root[i]=root[i-1]; 67 int f1=finda(root[i],t2),f2=finda(root[i],t3); 68 a r1=Query(root[i],1,n,f1),r2=Query(root[i],1,n,f2); 69 if(r1.bel!=r2.bel) 70 { 71 if(r1.siz<r2.siz) swap(r1,r2); 72 r1.siz+=r2.siz,r2.bel=r1.bel; 73 root[i]=Insert(root[i],1,n,r2.pst,r2); 74 root[i]=Insert(root[i],1,n,r1.pst,r1); 75 } 76 } 77 else if(t1==2) 78 root[i]=root[t2]; 79 else 80 { 81 scanf("%d",&t3),root[i]=root[i-1]; 82 printf("%d\n",finda(root[i],t2)==finda(root[i],t3)); 83 } 84 } 85 return 0; 86 }
View Code