• bzoj 3674: 可持久化并查集加强版 (启发式合并+主席树)


    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


    Input

     

    Output

     

    Sample Input

    5 6
    1 1 2
    3 1 2
    2 1
    3 0 3
    2 1
    3 1 2

    Sample Output

    1
    0
    1
     
    思路;
    就是bzoj 3673数据范围加大了下。。卡了下其他写法,启发式合并+主席树的写法不会被卡。。
    启发式合并也就是按秩合并,把小的并到大的。主席树里多维护一个数组dep,表示集合秩的大小。
    又水一道,美滋滋
     
    #include<bits/stdc++.h>
    using namespace std;
    #define mid int m = (l + r) >> 1
    const int M = 5e6 + 10;
    const int Max = 2e5+10;
    
    int sum[M],ls[M],rs[M],dep[M],n,idx,root[Max];
    void build(int l,int r,int &rt){
         rt = ++idx;
        if(l == r){
            sum[rt] = l;
            return ;
        }
        mid;
        build(l,m,ls[rt]); build(m+1,r,rs[rt]);
        return ;
    }
    
    void update(int old,int &rt,int p,int c,int l,int r){
        rt = ++idx; ls[rt] = ls[old]; rs[rt] = rs[old];
        dep[rt] = dep[old];
        if(l == r){
            sum[rt] = c;
            return ;
        }
        mid;
        if(p <= m) update(ls[old],ls[rt],p,c,l,m);
        else update(rs[old],rs[rt],p,c,m+1,r);
    }
    
    int query(int p,int l,int r,int rt){
        if(l == r) return rt;
        mid;
        if(p <= m) return query(p,l,m,ls[rt]);
        else return query(p,m+1,r,rs[rt]);
    }
    
    void add(int p,int l,int r,int rt){
        if(l == r){
            dep[rt] ++;
            return;
        }
        mid;
        if(p <= m) add(p,l,m,ls[rt]);
        else add(p,m+1,r,rs[rt]);
    }
    
    int fd(int x,int rt){
        int pos = query(x,1,n,rt);
        if(x == sum[pos]) return pos;
        return fd(sum[pos],rt);
    }
    
    int main()
    {
        int q,op,x,y,k;
        scanf("%d%d",&n,&q);
        build(1,n,root[0]);
        for(int i = 1;i <= q;i ++){
            scanf("%d",&op);
            if(op == 1){
                scanf("%d%d",&x,&y);
                root[i] = root[i-1];
                int fx = fd(x,root[i-1]);
                int fy = fd(y,root[i-1]);
                if(sum[fx] == sum[fy]) continue;
                if(dep[fx] > dep[fy]) swap(fx,fy);
                update(root[i-1],root[i],sum[fx],sum[fy],1,n);
                if(dep[fx] == dep[fy]) add(sum[fy],1,n,root[i]);
            }
            else if(op == 2){
                scanf("%d",&k);
                root[i] = root[k];
            }
            else {
                root[i] = root[i-1];
                scanf("%d%d",&x,&y);
                int fx = fd(x,root[i]);
                int fy = fd(y,root[i]);
                if(sum[fx] == sum[fy]) printf("1
    ");
                else printf("0
    ");
            }
        }
        return 0;
    }
     
  • 相关阅读:
    iframe自适应高度的多种方法方法
    [tomcat][mysql][JDK][maven][myEclipse][ubuntu][centOs][oracle]等下载地址整理
    解决电脑速度越来越慢的方法
    li:hover 上再IE6下就没有效果的解决方法
    各种常用文件后缀名详解
    ASP.net中网站访问量统计方法
    RabbbitMQ的配置 以在.NetCore 的CAP 使用RabbbitMQ 实现订阅与发布问题
    .netCore 根据模型生成数据库
    jsonp Ajax跨域请求
    IE8 placeholder兼容+Password兼容
  • 原文地址:https://www.cnblogs.com/kls123/p/9919223.html
Copyright © 2020-2023  润新知