可持久化並(xian)查(duan)集(shu)

隨便地點開了這道可持久化並查集,發現了真相...這和並查集有 PI 關係哦.除了find_father(並且還不能路徑壓縮),全都是線段樹0.0ios

 

題目連接: luogu.orggit

題目沒什麼描述,就是三個操做:ui

1. 合併 a bspa

2. 回到第 k 步操做(三個操做均算操做)code

3. 查詢 a b 在當前版本的並查集中是否在同一棵樹中blog

 

那麼...get

對於操做 1 :咱們在線段樹中修改節點 fa 的父親爲 fbstring

 


對於操做 2 :簡單,咱們直接把當前版本的根指向第 k 版本的根,一行就解決了(引發可持久化的罪魁禍首解決卻是簡單)
it

 

 

對於操做 3 :查詢 fafb 輸出就行了(貌似就操做 1 有點很差理解io

 

 

對於操做 1 ,模擬如圖:

 

 

 

代碼以下:

 

 1 //by Judge
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #define ls ch[now][0]
 7 #define rs ch[now][1]
 8 #define mid (l+r>>1)
 9 #define swap(a,b)  (a)^=(b)^=(a)^=(b)
10 using namespace std;
11 const int M=2e5+11; 
12 inline int read(){
13     int x=0,f=1; char c=getchar();
14     for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
15     for(;isdigit(c);c=getchar()) x=x*10+c-'0';
16     return x*f;
17 }
18 int n,m,cnt;
19 int ed[M<<5],f[M<<5],ch[M<<5][2],dep[M<<5];
20 inline void build(int& now,int l,int r){  //建樹,葉子節點認 左(右)端點 爲父親
21     now=++cnt; if(l==r){ f[now]=l; return ; }
22     build(ls,l,mid), build(rs,mid+1,r);
23 }
24 void update(int& now,int las,int l,int r,int pos,int fa){  //修改 pos 的父親爲 fa
25     now=++cnt; if(l==r){ f[now]=fa,dep[now]=dep[las]; return ; }
26     if(pos<=mid) update(ls,ch[las][0],l,mid,pos,fa);
27     else update(rs,ch[las][1],mid+1,r,pos,fa);
28 }
29 int query(int now,int l,int r,int pos){  //詢問在 now 版本中 pos 的節點編號
30     if(l==r) return now;
31     if(pos<=mid) return query(ls,l,mid,pos);
32     else return query(rs,mid+1,r,pos);
33 }
34 void add(int now,int l,int r,int pos){ //增長 now 版本中 pos 所在葉子節點的深度
35     if(l==r) { ++dep[now]; return ; }
36     if(pos<=mid) add(ls,l,mid,pos);
37     else add(rs,mid+1,r,pos);
38 }
39 int find(int ed,int x){  //查詢祖先
40     int fa=query(ed,1,n,x);
41     if(x==f[fa]) return fa;
42     return find(ed,f[fa]);
43 }
44 int main(){
45     n=read(),m=read(),build(ed[0],1,n);
46     for(int i=1,opt,a,b,f1,f2;i<=m;++i)
47         switch(opt=read()){
48             case 1:  //不顯然
49                 ed[i]=ed[i-1],a=read(),b=read();
50                 f1=find(ed[i],a),f2=find(ed[i],b);
51                 if(f[f1]==f[f2]) break;
52                 if(dep[f1]>dep[f2]) swap(f1,f2);
53                 update(ed[i],ed[i-1],1,n,f[f1],f[f2]);
54                 if(dep[f1]==dep[f2]) add(ed[i],1,n,f[f2]); break; //這裏 emmm,看上文
55             case 2: //顯然
56                 ed[i]=ed[read()]; break;
57             case 3:  //顯然
58                 ed[i]=ed[i-1],a=read(),b=read();
59                 f1=find(ed[i],a), f2=find(ed[i],b);
60                 puts(f[f1]==f[f2]?"1":"0"); break;
61         }
62     return 0;
63 }

 

上面代碼可能出鍋,下面代碼應該沒毛病...

 

 1 //by Judge
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #define ls ch[now][0]
 7 #define rs ch[now][1]
 8 #define mid (l+r>>1)
 9 #define swap(a,b)  (a)^=(b)^=(a)^=(b)
10 using namespace std;
11 const int M=2e5+11; 
12 inline int read(){
13     int x=0,f=1; char c=getchar();
14     for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
15     for(;isdigit(c);c=getchar()) x=x*10+c-'0';
16     return x*f;
17 }
18 int n,m,cnt;
19 int ed[M<<5],f[M<<5],ch[M<<5][2],dep[M<<5];
20 inline void build(int& now,int l,int r){
21     now=++cnt; if(l==r){ f[now]=l; return ; }
22     build(ls,l,mid), build(rs,mid+1,r);
23 }
24 void update(int& now,int las,int l,int r,int pos,int fa){
25     now=++cnt; if(l==r){ f[now]=fa,dep[now]=dep[las]; return ; }
26     ls=ch[las][0], rs=ch[las][1];
27     if(pos<=mid) update(ls,ch[las][0],l,mid,pos,fa);
28     else update(rs,ch[las][1],mid+1,r,pos,fa);
29 }
30 int query(int now,int l,int r,int pos){
31     if(l==r) return now;
32     if(pos<=mid) return query(ls,l,mid,pos);
33     else return query(rs,mid+1,r,pos);
34 }
35 void add(int now,int l,int r,int pos){
36     if(l==r) { ++dep[now]; return ; }
37     if(pos<=mid) add(ls,l,mid,pos);
38     else add(rs,mid+1,r,pos);
39 }
40 int find(int ed,int x){
41     int fa=query(ed,1,n,x);
42     if(x==f[fa]) return fa;
43     return find(ed,f[fa]);
44 }
45 int main(){
46     n=read(),m=read(),build(ed[0],1,n);
47     for(int i=1,opt,a,b,f1,f2;i<=m;++i)
48         switch(opt=read()){
49             case 1:
50                 ed[i]=ed[i-1],a=read(),b=read();
51                 f1=find(ed[i],a),f2=find(ed[i],b);
52                 if(f[f1]==f[f2]) break;
53                 if(dep[f1]>dep[f2]) swap(f1,f2);
54                 update(ed[i],ed[i-1],1,n,f[f1],f[f2]);
55                 if(dep[f1]==dep[f2]) add(ed[i],1,n,f[f2]); break;
56             case 2: ed[i]=ed[read()]; break;
57             case 3:
58                 ed[i]=ed[i-1],a=read(),b=read();
59                 f1=find(ed[i],a), f2=find(ed[i],b);
60                 puts(f[f1]==f[f2]?"1":"0"); break;
61         }
62     return 0;
63 }

 

 

 by Judge

相關文章
相關標籤/搜索