ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

Description: 自从zkysb出了可持久化并查集后…… hzwer:乱写能AC,暴力踩标程 KuribohG:我不路径压缩就过了! ndsf:暴力就可以轻松虐! zky:……
n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0 0<n,m<=2*10^5

用可持久化满二叉查找树实现可持久化数组,每次修改记录新的根

可持久化数组实现可持久化并查集

#include<cstdio>
const int N=10000000;
int ch[N][2];
int v[N],id[N];
int rts[200005],r;
int p=262145,la=0;
void build(int w,int s){
    if(s){
        build(w-s,s>>1);
        build(w+s,s>>1);
        ch[w][0]=w-s;
        ch[w][1]=w+s;
    }
    v[w]=id[w]=w;
}
int get(int w,int x){
    while(id[w]!=x)w=ch[w][id[w]<x];
    return v[w];
}
int set(int w,int x,int y){
    int u=p++;
    if(id[w]==x){
        ch[u][0]=ch[w][0];
        ch[u][1]=ch[w][1];
        v[u]=y;
    }else{
        bool d=id[w]<x;
        ch[u][d^1]=ch[w][d^1];
        ch[u][d]=set(ch[w][d],x,y);
        v[u]=v[w];
    }
    id[u]=id[w];
    return u;
}
int find(int x){
    int a=x,b;
    while((b=get(r,a))!=a)a=b;
    while((b=get(r,x))!=a)r=set(r,x,a),x=b;
    return a;
}
int n,m,o,a,b,c;
int main(){
    build(rts[0]=131072,65536);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        r=rts[i-1];
        scanf("%d",&o);
        if(o==1){
            scanf("%d%d",&a,&b);
            a=find(a^la);
            b=find(b^la);
            rts[i]=set(r,a,b);
        }else if(o==2){
            scanf("%d",&a);
            rts[i]=rts[a^la];
        }else{
            scanf("%d%d",&a,&b);
            printf("%d\n",la=find(a^la)==find(b^la));
            rts[i]=rts[i-1];
        }
    }
    return 0;
}

 

posted on 2016-01-31 15:28  nul  阅读(173)  评论(0编辑  收藏  举报