zoukankan      html  css  js  c++  java
  • Luogu 3402 可持久化并查集

    点开这题纯属无聊……不过既然写掉了,那就丢一个模板好了

    不得不说,可持久化并查集实现真的很暴力,就是把并查集的数组弄一个主席树可持久化。

    有一点要注意的是不能写路径压缩,这样跳版本的时候会错,所以弄一个按秩合并来降低时间复杂度。

    总时间复杂度$O(nlog^2n)$。

    听说用siz实现按秩合并会比较好,因为这样还能查询集合大小,有时间以后补上。

    Code:

    #include <cstdio>
    using namespace std;
    
    const int N = 1e5 + 5;
    const int M = 2e5 + 5;
    
    int n, qn;
    
    inline void read(int &X) {
        X = 0;
        char ch = 0;
        int op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    struct Node {
        int lc, rc, dep, fa;
    };
    
    namespace PUfs {
        Node s[N * 120];
        int root[M * 2], nodeCnt;
    
        #define mid ((l + r) >> 1)  
    
        void build(int &p, int l, int r) {
            p = ++nodeCnt;
            if(l == r) {
                s[p].fa = l;
                return;
            }
    
            build(s[p].lc, l, mid);
            build(s[p].rc, mid + 1, r);
        }
    
        void modify(int &p, int l, int r, int x, int f, int pre) {
            p = ++nodeCnt;
            if(l == r) {
                s[p].fa = f;
                s[p].dep = s[pre].dep;
                return;
            }
            
            s[p].lc = s[pre].lc, s[p].rc = s[pre].rc;
            if(x <= mid) modify(s[p].lc, l, mid, x, f, s[pre].lc);
            else modify(s[p].rc, mid + 1, r, x, f, s[pre].rc);
        }
    
        void add(int p, int l, int r, int x) {
            if(l == r) {
                s[p].dep++;
                return;
            }
            if(x <= mid) add(s[p].lc, l, mid, x);
            else add(s[p].rc, mid + 1, r, x);
        }
    
        int query(int p, int l, int r, int x) {
            if(l == r) return p;
    
            if(x <= mid) return query(s[p].lc, l, mid, x);
            else return query(s[p].rc, mid + 1, r, x);
        }
    
        int find(int now, int x) {
            int f = query(now, 1, n, x);
            if(s[f].fa == x) return f;
            return find(now, s[f].fa);
        } 
    
    } using namespace PUfs;
    
    inline void print(int p) {
        printf("%d: ", p);
        for(int j = 1; j <= n; j++)
            printf("%d ", s[find(root[p], j)].fa);  
    /*    for(int j = 1; j <= n; j++)
            printf("%d ", query(root[p], 1, n, j));  */
        printf("
    ");
    }   
    
    inline void swap(int &x, int &y) {
        int t = x;
        x = y;
        y = t;
    }
    
    int main() {
        read(n), read(qn);
    
        nodeCnt = 0;
        build(root[0], 1, n);
    
    //      print(0);
    
        for(int op, i = 1; i <= qn; i++) {
            read(op);
            if(op == 1) {
                root[i] = root[i - 1];
                int x, y;
                read(x), read(y);
                int fx = find(root[i], x), fy = find(root[i], y);
                if(s[fx].fa == s[fy].fa) continue;
                if(s[fx].dep > s[fy].dep) swap(fx, fy);
                modify(root[i], 1, n, s[fx].fa, s[fy].fa, root[i - 1]);
                if(s[fx].dep == s[fy].dep) add(root[i], 1, n, s[fy].fa);
            }
            if(op == 2) {
                int k;
                read(k);
                root[i] = root[k];
            } 
            if(op == 3) {
                root[i] = root[i - 1];
                int x, y;
                read(x), read(y);
                int fx = find(root[i], x), fy = find(root[i], y);
                if(s[fx].fa == s[fy].fa) puts("1");
                else puts("0");
            }
    //      print(i);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    智能指针
    C++学习之对类中的成员函数的定义和声明最后添加一个const作用
    动态链接,静态链接库
    Java 位运算
    Java 工具类
    Java 枚举
    Java 内部类
    Java 异常机制
    Java hashCode 和 equals
    Java 字节流和字符流
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9478101.html
Copyright © 2011-2022 走看看