【洛谷 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\n", t[find(read())].val == t[find(read())].val);
      }
    }
    return 0;
}

posted @ 2018-11-09 15:24  Qihoo360  阅读(187)  评论(0编辑  收藏  举报
You're powerful!