2017.9.27 可持久化并查集 失败总结

来源:互联网 发布:juniper network mac 编辑:程序博客网 时间:2024/06/07 03:02

这个题目就是误导你的,据说zky用了rope。。所以苦于用并查集强行持久的似乎不太好做

这个题可以根据并查集的原理只加启发式合并优化

这样就可以常数巨大、空间巨大的nlogn了


启发式合并的过程 对于数值上来说 就是一个fu数组赋值为另一个的fu数组,所以相当于单点修改

sz单点加

撤销过程相当于回到前几个询问


很像主席树啊,还是单点修改,,就比较好做了


注:

1、复制粘贴注意修改

2、注意查询时用上一棵树

3、注意开点的情况,,已经有了就不能再建了


码:

#include<iostream>#include<cstdio>using namespace std;#define N 100005int ch[(N<<2)*60][2],fu[(N<<2)*60],sz[(N<<2)*60],tot,op,a,b,c,cz,rt[N],n,m,i,j,x,y;void jian(int o,int l,int r){if(l==r){sz[o]=1;fu[o]=l;return ;}int mid=(l+r)>>1;ch[o][0]=++tot;ch[o][1]=++tot;jian(ch[o][0],l,mid);jian(ch[o][1],mid+1,r);}void gai(int o,int l,int r,int last){if(l==r){if(op==1){fu[o]=c;sz[o]=sz[last];        }          if(op==2)        {    sz[o]+=c;    fu[o]=fu[last];}        if(op==3)        {        c=sz[o];}if(op==4)        {        c=fu[o];}        return;}int mid=(l+r)>>1;if(a<=mid){if(ch[o][0]==0)ch[o][0]=++tot;if(ch[o][1]==0)ch[o][1]=ch[last][1];gai(ch[o][0],l,mid,ch[last][0]);}else{if(ch[o][1]==0)ch[o][1]=++tot;if(ch[o][0]==0)ch[o][0]=ch[last][0];gai(ch[o][1],mid+1,r,ch[last][1]);}}int main(){scanf("%d%d",&n,&m);rt[0]=++tot;jian(1,1,n);//syg=1;for(i=1;i<=m;i++){scanf("%d",&cz);if(cz==1){scanf("%d%d",&x,&y);rt[i]=++tot;op=4;c=x;a=0;while(a!=c){a=c;gai(rt[i-1],1,n,rt[i-1]);    }    int c1=c;c=y;a=0;while(a!=c){a=c;gai(rt[i-1],1,n,rt[i-1]);    } int c2=c;int cc1,cc2;op=3;a=c1;gai(rt[i-1],1,n,rt[i-1]);cc1=c;a=c2;gai(rt[i-1],1,n,rt[i-1]);cc2=c;if(cc1>cc2)swap(cc1,cc2);op=1;a=c1;c=c2;gai(rt[i],1,n,rt[i-1]);op=2;a=c2;c=cc1;gai(rt[i],1,n,rt[i-1]);}if(cz==2){scanf("%d",&x);rt[i]=rt[x];//syg=i;}if(cz==3){scanf("%d%d",&x,&y);rt[i]=rt[i-1];op=4;c=x;a=0;while(a!=c){a=c;gai(rt[i-1],1,n,rt[i-1]);    }    int c1=c;c=y;a=0;while(a!=c){a=c;gai(rt[i-1],1,n,rt[i-1]);    } int c2=c;if(c1==c2){printf("1\n");}else printf("0\n");}}}


原创粉丝点击