【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版
可持久化并查集
Orz hzwer & zyf
呃学习了一下可持久化并查集的姿势……其实并查集就是一个fa数组(可能还要带一个size或rank数组),那么我们对并查集可持久化其实就是实现一个可持久化数组……
那么我们用可持久化线段树实现一下可持久化数组就可以了- -
一开始我比较傻逼,想着:中间的叶子节点不是没用嘛?什么信息也不存……然而如果不这样的话,难道你每次修改,新建N个指针吗?这样可以保证每次只新建O(logn)个节点出来……
(是不是a+b problem也是类似的原因?并不知道诶……去做下看看好了)
嘛那么这里维护一下fa和size就可以了。。。
1 /************************************************************** 2 Problem: 3673 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:64 ms 7 Memory:7608 kb 8 ****************************************************************/ 9 10 //BZOJ 3673 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=2e4+10; 29 /*******************template********************/ 30 31 int n,m,cnt,rt[N]; 32 33 struct node{ 34 int l,r,v,size; 35 }t[N*20]; 36 #define L t[o].l 37 #define R t[o].r 38 #define mid (l+r>>1) 39 #define lch L,l,mid 40 #define rch R,mid+1,r 41 42 void build(int &o,int l,int r){ 43 o=++cnt; 44 if (l==r) {t[o].v=l;t[o].size=1;return;} 45 build(lch); 46 build(rch); 47 } 48 void update(int &o,int l,int r,int pos,int v){ 49 t[++cnt]=t[o], o=cnt; 50 if (l==r) {t[o].v=v; return;} 51 if (pos<=mid) update(lch,pos,v); 52 else update(rch,pos,v); 53 } 54 void modify(int &o,int l,int r,int pos,int v){ 55 t[++cnt]=t[o], o=cnt; 56 if (l==r) {t[o].size+=v; return;} 57 if (pos<=mid) modify(lch,pos,v); 58 else modify(rch,pos,v); 59 } 60 int queryv(int o,int l,int r,int pos){ 61 if (l==r) return t[o].v; 62 if (pos<=mid) return queryv(lch,pos); 63 else return queryv(rch,pos); 64 } 65 int querysz(int o,int l,int r,int pos){ 66 if (l==r) return t[o].size; 67 if (pos<=mid) return querysz(lch,pos); 68 else return querysz(rch,pos); 69 } 70 int getfa(int x,int y){ 71 int now=y,nxt=queryv(rt[x],1,n,y); 72 while(now!=nxt){ 73 now=nxt; 74 nxt=queryv(rt[x],1,n,now); 75 } 76 return now; 77 } 78 79 int main(){ 80 #ifndef ONLINE_JUDGE 81 freopen("3673.in","r",stdin); 82 freopen("3673.out","w",stdout); 83 #endif 84 n=getint(); m=getint(); 85 build(rt[0],1,n); 86 int cmd,x,y,ans=0; 87 F(i,1,m){ 88 rt[i]=rt[i-1]; 89 cmd=getint(); 90 if (cmd==1){ 91 x=getint(); y=getint(); 92 int f1=getfa(i,x),f2=getfa(i,y), 93 s1=querysz(rt[i],1,n,f1),s2=querysz(rt[i],1,n,f2); 94 if (s1<s2) swap(f1,f2); 95 modify(rt[i],1,n,f1,s2); 96 update(rt[i],1,n,f2,f1); 97 }else if (cmd==2){ 98 rt[i]=rt[getint()]; 99 }else if (cmd==3){ 100 x=getint(); y=getint(); 101 int f1=getfa(i,x),f2=getfa(i,y); 102 printf("%d\n",ans=(f1==f2)); 103 } 104 } 105 return 0; 106 }
1 /************************************************************** 2 Problem: 3674 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1336 ms 7 Memory:158308 kb 8 ****************************************************************/ 9 10 //BZOJ 3674 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=2e5+10; 29 /*******************template********************/ 30 31 int n,m,cnt,rt[N]; 32 33 struct node{ 34 int l,r,v,size; 35 }t[10000010]; 36 #define L t[o].l 37 #define R t[o].r 38 #define mid (l+r>>1) 39 #define lch L,l,mid 40 #define rch R,mid+1,r 41 42 void build(int &o,int l,int r){ 43 o=++cnt; 44 if (l==r) {t[o].v=l;t[o].size=1;return;} 45 build(lch); 46 build(rch); 47 } 48 void update(int &o,int l,int r,int pos,int v){ 49 t[++cnt]=t[o], o=cnt; 50 if (l==r) {t[o].v=v; return;} 51 if (pos<=mid) update(lch,pos,v); 52 else update(rch,pos,v); 53 } 54 void modify(int &o,int l,int r,int pos,int v){ 55 t[++cnt]=t[o], o=cnt; 56 if (l==r) {t[o].size+=v; return;} 57 if (pos<=mid) modify(lch,pos,v); 58 else modify(rch,pos,v); 59 } 60 int queryv(int o,int l,int r,int pos){ 61 if (l==r) return t[o].v; 62 if (pos<=mid) return queryv(lch,pos); 63 else return queryv(rch,pos); 64 } 65 int querysz(int o,int l,int r,int pos){ 66 if (l==r) return t[o].size; 67 if (pos<=mid) return querysz(lch,pos); 68 else return querysz(rch,pos); 69 } 70 int getfa(int x,int y){ 71 int now=y,nxt=queryv(rt[x],1,n,y); 72 while(now!=nxt){ 73 now=nxt; 74 nxt=queryv(rt[x],1,n,now); 75 } 76 return now; 77 } 78 79 int main(){ 80 #ifndef ONLINE_JUDGE 81 freopen("3674.in","r",stdin); 82 freopen("3674.out","w",stdout); 83 #endif 84 n=getint(); m=getint(); 85 build(rt[0],1,n); 86 int cmd,x,y,ans=0; 87 F(i,1,m){ 88 rt[i]=rt[i-1]; 89 cmd=getint(); 90 if (cmd==1){ 91 x=getint()^ans; y=getint()^ans; 92 int f1=getfa(i,x),f2=getfa(i,y), 93 s1=querysz(rt[i],1,n,f1),s2=querysz(rt[i],1,n,f2); 94 if (s1<s2) swap(f1,f2); 95 modify(rt[i],1,n,f1,s2); 96 update(rt[i],1,n,f2,f1); 97 }else if (cmd==2){ 98 rt[i]=rt[getint()^ans]; 99 }else if (cmd==3){ 100 x=getint()^ans; y=getint()^ans; 101 int f1=getfa(i,x),f2=getfa(i,y); 102 printf("%d\n",ans=(f1==f2)); 103 } 104 } 105 return 0; 106 }
(3674为强制在线,且数据范围20W)
3673: 可持久化并查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 757 Solved: 319
[Submit][Status][Discuss]
Description
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
0<n,m<=2*10^4
Input
Output
Sample Input
5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
1
0
1
0
1