可持久化并查集求助启发式合并和按秩合并
查看原帖
可持久化并查集求助启发式合并和按秩合并
583610
DrAlfred楼主2024/8/1 12:48
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
struct Node {
    int l, r, ls, rs, siz, fa;
    inline int mid(void) { return (l + r) >> 1; }
} tr[N << 5];
int n, m, opt, x, y, mem, rt, root[N << 1];
inline int clone(int p) {
    return tr[++mem] = tr[p], mem;
}
inline void build(int &p, int l, int r) {
    p = ++mem, tr[p] = {l, r};
    if (l == r) {
        tr[p].siz = 1, tr[p].fa = l;
    } else {
        const int m = (l + r) >> 1;
        build(tr[p].ls, l, m), build(tr[p].rs, m + 1, r);
    }
}
inline int add_siz(int p, int x, int v) {
    p = clone(p);
    if (tr[p].l == tr[p].r) {
        tr[p].siz += v;
    } else {
        if (x <= tr[p].mid()) {
            tr[p].ls = add_siz(tr[p].ls, x, v);
        } else {
            tr[p].rs = add_siz(tr[p].rs, x, v);
        }
    }
    return p;
}
inline int query_siz(int p, int x) {
    if (tr[p].l == tr[p].r) return tr[p].siz;
    return query_siz(x <= tr[p].mid() ? tr[p].ls : tr[p].rs, x);
}
inline int set_fa(int p, int x, int v) {
    p = clone(p);
    if (tr[p].l == tr[p].r) {
        tr[p].fa = v;
    } else {
        if (x <= tr[p].mid()) {
            tr[p].ls = set_fa(tr[p].ls, x, v);
        } else {
            tr[p].rs = set_fa(tr[p].rs, x, v);
        }
    }
    return p;
}
inline int query_fa(int p, int x) {
    if (tr[p].l == tr[p].r) return tr[p].fa;
    return query_fa(x <= tr[p].mid() ? tr[p].ls : tr[p].rs, x);
}
inline int find(int x, int rt) {
    int fx = query_fa(rt, x);
    return fx == x ? x : find(fx, rt);
}
inline void merge(int x, int y, int from, int &to) {
    int fx = find(x, from), fy = find(y, from);
    if (fx == fy) {
        return to = from, void();
    }
    int sx = query_siz(from, fx);
    int sy = query_siz(from, fy);
    if (sx < sy) std::swap(fx, fy);
    to = set_fa(from, fy, fx), to = add_siz(to, fx, sy);
}
inline bool same(int x, int y, int rt) {
    return find(x, rt) == find(y, rt);
}
int main(int argc, char const *argv[]) {
    ios::sync_with_stdio(false);
    cin.tie(NULL), cout.tie(NULL);
    cin >> n >> m, build(root[0], 1, n);
    for (int i = 1; i <= m; i++) {
        cin >> opt >> x;
        if (opt == 1) {
            cin >> y, merge(x, y, root[i - 1], root[i]);
        } else if (opt == 2) {
            root[i] = rt = root[x];
        } else {
            cin >> y, root[i] = root[i - 1];
            cout << same(x, y, root[i]) << '\n';
        }
    }
    return 0;
}

rt,这份代码使用了启发式合并的并查集,TLE on #2,5,6,11,14 想问一下对于可持久化并查集,启发式合并和按秩合并有什么区别吗?下载数据在本地大概要跑 3s.

2024/8/1 12:48
加载中...