zoukankan      html  css  js  c++  java
  • [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
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    nginx: [emerg] the size 10485760 of shared memory zone "cache_one" conflicts with already declared size 0
    ruby 删除文件夹(包括文件夹中的文件夹和文件)
    nisi 脚本示例
    将node-expat扩展编译至node.exe中
    将odbc扩展编译至nodejs程序集中
    微信小程序数据传递基本
    Java环境配置
    Angular环境配置
    mysql中常用的数据类型
    html中a标签的4个伪类样式
  • 原文地址:https://www.cnblogs.com/shenben/p/6472792.html
Copyright © 2011-2022 走看看