可持久化并查集模板

#include<bits/stdc++.h>
using namespace std;

const int MAXN=1e6+2333;

int n,m;
int a[MAXN];

struct Persistable_Segment_Tree{
    struct Node{
        int val,L,R,dep;
    }t[MAXN*20];
    int cnt,rt[MAXN*20];
    void build_tree(int &root,int l,int r){
        root=++cnt;
        if (l==r) return (void)(t[root].val=l,t[root].dep=1);
        int mid=l+r>>1;
        build_tree(t[root].L,l,mid);
        build_tree(t[root].R,mid+1,r);
    }
    void update(int &root,int las,int l,int r,int q,int opt){
        root=++cnt;
        t[root]=t[las];
        if (l==r) return (void)(t[root].val=opt);
        int mid=l+r>>1;
        if (q<=mid) update(t[root].L,t[las].L,l,mid,q,opt);
        else update(t[root].R,t[las].R,mid+1,r,q,opt);
    }
    void add_deep(int root,int l,int r,int q){
        if (l==r) return (void)(t[root].dep++);
        int mid=l+r>>1;
        if (q<=mid) add_deep(t[root].L,l,mid,q);
        else add_deep(t[root].R,mid+1,r,q);
    }
    int query(int root,int l,int r,int q){
        if (l==r) return root;
        int mid=l+r>>1;
        if (q<=mid) return query(t[root].L,l,mid,q);
        else return query(t[root].R,mid+1,r,q);
    }
}T;

int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)){ if (ch=='-') f=-1; ch=getchar(); }
    while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;
}

int find(int &rt,int x){
    int tmp=T.query(rt,1,n,x);
    while (x!=T.t[tmp].val)
        x=T.t[tmp].val,tmp=T.query(rt,1,n,x);
    return tmp;
}

int main(){
    n=read(),m=read();
    T.cnt=0,T.build_tree(T.rt[0],1,n);
    int opt,x,y,u,v,dep_x,dep_y;
    for (int i=1;i<=m;i++){
        opt=read();
        if (opt==1){ // 合并集合
            x=find(T.rt[i-1],read()),y=find(T.rt[i-1],read());
            u=T.t[x].val,v=T.t[y].val;
            dep_x=T.t[x].dep,dep_y=T.t[y].dep;
            if (u!=v){
                if (dep_x>dep_y) swap(u,v);
                T.update(T.rt[i],T.rt[i-1],1,n,u,v);
                if (dep_x==dep_y)
                    T.add_deep(T.rt[i],1,n,v);
            }
            else
                T.rt[i]=T.rt[i-1];
        }
        else if (opt==2){ // 回到历史版本
            x=read();
            T.rt[i]=T.rt[x];
        }
        else if (opt==3){ //查询是否在同一集合
            x=find(T.rt[i-1],read()),y=find(T.rt[i-1],read());
            T.rt[i]=T.rt[i-1];
            printf("%d\n",x!=y ? 0:1);
        }
    }
    return 0;
}

 

posted @ 2018-11-02 15:20  QingCai_DCF  阅读(220)  评论(0编辑  收藏  举报