zoukankan      html  css  js  c++  java
  • 【洛谷 P3402】 【模板】可持久化并查集

    题目链接

    可持久化并查集,就是用可持久化线段树维护每个版本每个节点的父亲,这样显然是不能路径压缩的,否则我们需要恢复太多状态。
    但是这并不影响我们启发式合并,于是,每次把深度小的连通块向深度大的上并就好了。

    #include <cstdio>
    #define re register
    inline int read(){
        int s = 0, w = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
        while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
        return s * w;
    }
    const int MAXN = 100010;
    const int MAXM = 200010;
    struct SegTree{
        int lc, rc, val, dep;
    }t[MAXN * 20];
    int cnt, opt, a, b, root[MAXM], rt, n, m;
    int build(int l, int r){
        int id = ++cnt;
        if(l == r){
          t[id].val = l;
          return id;
        }
        int mid = (l + r) >> 1;
        t[id].lc = build(l, mid);
        t[id].rc = build(mid + 1, r);
        return id;
    }
    int query(int now, int l, int r, int x){
        if(l == r) return now;
        int mid = (l + r) >> 1;
        return x <= mid ? query(t[now].lc, l, mid, x) : query(t[now].rc, mid + 1, r, x);
    }
    int update(int now, int l, int r, int x, int p){
        int id = ++cnt;
        t[id] = t[now];
        if(l == r){ t[id].val = p; return id; }
        int mid = (l + r) >> 1;
        if(x <= mid) t[id].lc = update(t[now].lc, l, mid, x, p);
        else t[id].rc = update(t[now].rc, mid + 1, r, x, p);
        return id;
    }
    int find(int x){
        int now = query(rt, 1, n, x);
        if(t[now].val == x) return now;
        return find(t[now].val);
    }
    void updep(int now, int l, int r, int x){
        if(l == r){ ++t[now].dep; return; }
        int mid = (l + r) >> 1;
        if(x <= mid) updep(t[now].lc, l, mid, x);
        else updep(t[now].rc, mid + 1, r, x);
    }
    int main(){
        n = read(); m = read();
        root[0] = build(1, n);
        for(int i = 1; i <= m; ++i){
          opt = read();
          rt = root[i - 1];
          if(opt == 1){
            a = read(); b = read();
            int fa = find(a), fb = find(b);
            if(t[fa].dep < t[fb].dep){
              root[i] = update(root[i - 1], 1, n, t[fa].val, t[fb].val);
              if(t[fa].dep == t[fb].dep) updep(root[i], 1, n, t[fb].val);
            }
            else{
              root[i] = update(root[i - 1], 1, n, t[fb].val, t[fa].val);
              if(t[fa].dep == t[fb].dep) updep(root[i], 1, n, t[fa].val);
            }
          }
          if(opt == 2){
            rt = root[i] = root[read()];
          }
          if(opt == 3){
            rt = root[i] = root[i - 1];
            printf("%d
    ", t[find(read())].val == t[find(read())].val);
          }
        }
        return 0;
    }
    
    
  • 相关阅读:
    自然语言处理1-1 算法时间复杂度
    tensorflow2.0(1):简介
    基于PKCS#11的应用架构
    数字证书应用改造需求调研-2015-10-19
    签名验证工具Aloaha Sign
    PDF签名应用研究小结
    用bcp导sql server数据到excel文件
    无线网卡和有线网卡的嗅探模式的区别
    Tomcat6源代码在Eclipse里调试简要说明
    OpenLDAP 主从复制配置
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9935355.html
Copyright © 2011-2022 走看看