[BZOJ3674]可持久化并查集加强版

[BZOJ3674]可持久化并查集加强版

★★★   输入文件:bzoj_3974.in   输出文件:bzoj_3974.out   简单对比
时间限制:3 s   内存限制:256 MB

 

DescriptionDescription:

自从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

InputOutputSample Input

5 6

1 1 2

3 1 2

2 1

3 0 3

2 1

3 1 2

Sample Output

1

0

1

by zky

/*
可持久化线段树+启发式合并.(引自yjy) 
可持久化线段树维护当前状态下集合的关系和秩的信息.
所谓的秩就是以该元素为代表元的所有元素中的最大深度.
然后按秩合并的目的是为了降常. 
每个叶节点维护一颗线段树 
合并的时候在权值线段树的子节点加一个数,
相当于连了一条边 表示有关系存在.
要先查询要将合并两个元素的父亲所在位置.
显然只有在两个集合秩相同时才更新秩.
*/
#include<cstdio>
#include<iostream>
using namespace std;
const int N=2e5+5,Z=N*20;
int n,m;
int sz,root[N],ls[Z],rs[Z],dep[Z],fax[Z];
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void build(int &k,int l,int r){
    k=++sz;
    if(l==r){
        fax[k]=l;return ;
    }
    int mid=l+r>>1;
    build(ls[k],l,mid);
    build(rs[k],mid+1,r);
}
int find_pos(int &k,int l,int r,int x){
    if(l==r) return k;
    int mid=l+r>>1;
    if(x<=mid) return find_pos(ls[k],l,mid,x);
    else return find_pos(rs[k],mid+1,r,x);
}
int get_fa(int &k,int x){//非路径压缩 
    int p=find_pos(k,1,n,x);
    if(fax[p]==x) return p;
    else return get_fa(k,fax[p]);
}
void insert(int &k,int last,int l,int r,int x,int y){
    k=++sz;
    if(l==r){fax[k]=y;dep[k]=dep[last];return ;}
    ls[k]=ls[last];
    rs[k]=rs[last];
    int mid=l+r>>1;
    if(x<=mid) insert(ls[k],ls[last],l,mid,x,y);
    else insert(rs[k],rs[last],mid+1,r,x,y);
}
void update(int &k,int l,int r,int v){
    if(l==r){dep[k]++;return ;}
    int mid=l+r>>1;
    if(v<=mid) update(ls[k],l,mid,v);
    else update(rs[k],mid+1,r,v);
}
void merge(int l1,int l2,int i){
    if(dep[l1]>dep[l2]) swap(l1,l2);
    insert(root[i],root[i-1],1,n,fax[l1],fax[l2]);
    if(dep[l1]==dep[l2]) update(root[i],1,n,fax[l2]);
}
int main(){
    freopen("bzoj_3974.in","r",stdin);
    freopen("bzoj_3974.out","w",stdout);
    n=read();m=read();
    build(root[0],1,n);
    for(int i=1,opt,x,y,l1,l2,ans=0;i<=m;i++){
        opt=read();x=read()^ans;if(opt&1) y=read()^ans;
        root[i]=root[opt&1?i-1:x];
        if(opt==1){
            l1=get_fa(root[i],x);
            l2=get_fa(root[i],y);
            if(l1!=l2) merge(l1,l2,i);
        }
        if(opt==3){
            l1=get_fa(root[i],x);
            l2=get_fa(root[i],y);
            ans=(l1==l2);
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

posted @ 2017-02-27 11:10  神犇(shenben)  阅读(730)  评论(1编辑  收藏  举报