解题:洛谷3402 可持久化并查集

题面

滚下去补学考之前更一发

基于可持久化线段树实现(我不很喜欢“主席树”这个名字),注意不能路径压缩,首先这与可持久化的思想冲突(即尽量利用之前已有的部分,只修改有修改的部分,路径压缩压完了岂不是gg),其次每次压缩还会有一个log的时间复杂度(查询),然后复杂度就是$O(nlog 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
",finda(root[i],t2)==finda(root[i],t3));
83         } 
84     }
85     return 0;
86 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9989412.html