【BZOJ3673】可持久化并查集

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/81631395

【题目链接】

【双倍经验链接】

【思路要点】

  • 用可持久化线段树实现可持久化数组。
  • 时间复杂度 O ( N L o g 2 N )

【代码】


#include<bits/stdc++.h>

using namespace std;

#define MAXN  200005


#define MAXP  10000005

template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
struct Persisent_Segment_Tree {
  struct Node {
      int lc, rc;
      //Non-leaf : lc -> leftchild, rc -> rightchild
      //Leaf : lc -> father, rc -> size
  } a[MAXP];
  int root[MAXN];
  int n, size, version;
  void build(int &root, int l, int r) {
      if (root == 0) root = ++size;
      if (l == r) {
          a[root].lc = l;
          a[root].rc = 1;
          return;
      }
      int mid = (l + r) / 2;
      build(a[root].lc, l, mid);
      build(a[root].rc, mid + 1, r);
  }
  void init(int x) {
      n = x;
      size = 0;
      version = 0;
      build(root[0], 1, n);
  }
  void restore(int old) {
      root[++version] = root[old];
  }
  pair <int, int> query(int root, int l, int r, int pos) {
      if (l == r) return make_pair(a[root].lc, a[root].rc);
      int mid = (l + r) / 2;
      if (mid >= pos) return query(a[root].lc, l, mid, pos);
      else return query(a[root].rc, mid + 1, r, pos);
  }
  pair <int, int> getroot(int x) {
      pair <int, int> tmp = query(root[version], 1, n, x);
      if (tmp.first == x) return tmp;
      else return getroot(tmp.first);
  }
  int modify(int root, int l, int r, int pos, int vl, int vr) {
      if (l == r) {
          size++;
          a[size].lc = vl;
          a[size].rc = vr;
          return size;
      }
      int mid = (l + r) / 2;
      int ans = ++size;
      a[ans] = a[root];
      if (mid >= pos) a[ans].lc = modify(a[root].lc, l, mid, pos, vl, vr);
      else a[ans].rc = modify(a[root].rc, mid + 1, r, pos, vl, vr);
      return ans;
  }
  void merge(int x, int y) {
      pair <int, int> rx = getroot(x);
      pair <int, int> ry = getroot(y);
      if (rx.second < ry.second) {
          version++;
          root[version] = root[version - 1];
          root[version] = modify(root[version], 1, n, rx.first, ry.first, rx.second);
          root[version] = modify(root[version], 1, n, ry.first, ry.first, rx.second + ry.second);
      } else {
          version++;
          root[version] = root[version - 1];
          root[version] = modify(root[version], 1, n, ry.first, rx.first, ry.second);
          root[version] = modify(root[version], 1, n, rx.first, rx.first, rx.second + ry.second);
      }
  }
  int query(int x, int y) {
      version++;
      root[version] = root[version - 1];
      pair <int, int> rx = getroot(x);
      pair <int, int> ry = getroot(y);
      return rx.first == ry.first;
  }
} PST;
int main() {
  int n, m;
  read(n), read(m);
  PST.init(n);
  for (int i = 1; i <= m; i++) {
      int opt, x, y;
      read(opt);
      if (opt == 1) {
          read(x), read(y);
          PST.merge(x, y);
      }
      if (opt == 2) {
          read(x);
          PST.restore(x);
      }
      if (opt == 3) {
          read(x), read(y);
          printf("%d\n", PST.query(x, y));
      }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/81631395