【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 }
View Code(3673)
  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 }
View Code(3674)

(3674为强制在线,且数据范围20W)

3673: 可持久化并查集 by zky

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

1
0
1




HINT

Source

[Submit][Status][Discuss]
posted @ 2015-06-19 09:00  Tunix  阅读(365)  评论(0编辑  收藏  举报