zoukankan      html  css  js  c++  java
  • 洛谷P3402 可持久化并查集 题解

    题目链接:https://www.luogu.com.cn/problem/P3402

    题目大意:

    给定 (n) 个集合,第 (i) 个集合内初始状态下只有一个数,为 (i)

    (m) 次操作。操作分为 (3) 种:

    • 1 a b 合并 (a,b) 所在集合;

    • 2 k 回到第 (k) 次操作(执行三种操作中的任意一种都记为一次操作)之后的状态;

    • 3 a b 询问 (a,b) 是否属于同一集合,如果是则输出 (1) ,否则输出 (0)

    解题思路:

    可持久化并查集。并查集 按秩合并,不要路径压缩。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    struct Tree {
        int l, r,val;
    } tree[maxn*80];
    int tot, rootfa[maxn*2], rootdep[maxn*2];
    int n, m;
    void build(int l, int r, int& rt) {
        rt = ++tot;
        if (l == r) {
            tree[rt].val = l;
            return;
        }
        int mid = (l + r) / 2;
        build(l, mid, tree[rt].l);
        build(mid+1, r, tree[rt].r);
    }
    void update(int p, int val, int l, int r, int pt, int &rt) {
        tree[rt = ++tot] = tree[pt];
        if (l == r) {
            tree[rt].val = val;
            return;
        }
        int mid = (l + r) / 2;
        if (p <= mid)
            update(p, val, l, mid, tree[pt].l, tree[rt].l);
        else
            update(p, val, mid+1, r, tree[pt].r, tree[rt].r);
    }
    int query(int p, int l, int r, int rt) {
        if (l == r) return tree[rt].val;
        int mid = (l + r) / 2;
        if (p <= mid)
            return query(p, l, mid, tree[rt].l);
        else
            return query(p, mid+1, r, tree[rt].r);
    }
    int ffind(int ver, int x) {
        int fa = query(x, 1, n, rootfa[ver]);
        return fa == x ? x : ffind(ver, fa);
    }
    void funion(int ver, int x, int y) {
        x = ffind(ver-1, x);
        y = ffind(ver-1, y);
        if (x == y) {
            rootfa[ver] = rootfa[ver-1];
            rootdep[ver] = rootdep[ver-1];
        }
        else {
            int depx = query(x, 1, n, rootdep[ver-1]);
            int depy = query(y, 1, n, rootdep[ver-1]);
            if (depx > depy) swap(x, y);
            update(x, y, 1, n, rootfa[ver-1], rootfa[ver]);
            if (depx == depy) {
                update(y, depy+1, 1, n, rootdep[ver-1], rootdep[ver]);
            }
            else {
                rootdep[ver] = rootdep[ver-1];
            }
        }
    }
    int main() {
        ios::sync_with_stdio(0);
        cin >> n >> m;
        build(1, n, rootfa[0]);
        for (int i = 1; i <= m; i ++) {
            int op, k, a, b;
            cin >> op;
            if (op == 2) cin >> k;
            else cin >> a >> b;
            if (op == 1) {  // 合并a,b所在集合
                funion(i, a, b);
            }
            else if (op == 2) { // 回到第k次操作
                rootfa[i] = rootfa[k];
                rootdep[i] = rootdep[k];
            }
            else {  // 询问a,b是否属于同一集合
                rootfa[i] = rootfa[i-1];
                rootdep[i] = rootdep[i-1];
                cout << (ffind(i, a) == ffind(i, b) ? 1 : 0) << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    ireport字体无效处理
    java web调用打印机打印pdf文件
    Extjs中如何在一行textfield后面增加文字提示
    java 压缩文件
    filter加载springbean
    Elasticsearch问题记录
    dubbo管控台的安装记录及dubbo开发调试记录
    mysql索引整理
    fastdfs集群搭建3
    fastdfs集群搭建2
  • 原文地址:https://www.cnblogs.com/quanjun/p/15523414.html
Copyright © 2011-2022 走看看