• [BZOJ 3674]可持久化并查集加强版


    Description

    自从zkysb出了可持久化并查集后……
    hzwer:乱写能AC,暴力踩标程
    KuribohG:我不路径压缩就过了!
    ndsf:暴力就可以轻松虐!
    zky:……

    n个集合 m个操作
    操作:
    1 a b 合并a,b所在集合
    2 k 回到第k次操作之后的状态(查询算作操作)
    3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
    请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
    0<n,m<=2*10^5

    Sample Input

    5 6
    1 1 2
    3 1 2
    2 1
    3 0 3
    2 1
    3 1 2

    Sample Output

    1
    0
    1

    题解

    用启发式合并的话,我们发现对历史并查集只需要将深度小的根节点的父亲修改就可以了。

    那么可持久化数组单点修改就ojbk了。可持久化数组用主席树实现。

      1 //It is made by Awson on 2017.10.5
      2 #include <map>
      3 #include <set>
      4 #include <cmath>
      5 #include <ctime>
      6 #include <queue>
      7 #include <stack>
      8 #include <vector>
      9 #include <cstdio>
     10 #include <string>
     11 #include <cstdlib>
     12 #include <cstring>
     13 #include <iostream>
     14 #include <algorithm>
     15 #define LL long long
     16 #define Max(a, b) ((a) > (b) ? (a) : (b))
     17 #define Min(a, b) ((a) < (b) ? (a) : (b))
     18 #define sqr(x) ((x)*(x))
     19 using namespace std;
     20 const int N = 2e5;
     21 void read(int &x) {
     22   char ch; bool flag = 0;
     23   for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
     24   for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
     25   x *= 1-2*flag;
     26 }
     27 
     28 struct node {
     29   int key;
     30   node *child[2];
     31 }sgm[N*30+5], *pos = sgm;
     32 node* root[N+5];
     33 int dep[N+5];
     34 int n, m, lastans;
     35 int opt, a, b;
     36 
     37 void build(node* &o, int l, int r) {
     38   if (l == r) {
     39     dep[l] = 1;
     40     return;
     41   }
     42   int mid = (l+r)>>1;
     43   o->child[0] = ++pos, build(o->child[0], l, mid);
     44   o->child[1] = ++pos, build(o->child[1], mid+1, r);
     45 }
     46 void update(node* &o, int l, int r, int loc, int val) {
     47   node* t = o;
     48   o = ++pos;
     49   if (l == r) {
     50     o->key = val;
     51     return;
     52   } else {
     53     o->child[0] = t->child[0];
     54     o->child[1] = t->child[1];
     55   }
     56   int mid = (l+r)>>1;
     57   if (loc <= mid) update(o->child[0], l, mid, loc, val);
     58   else update(o->child[1], mid+1, r, loc, val);
     59 }
     60 int query(node *o, int l, int r, int loc) {
     61   if (l == r) return o->key;
     62   int mid = (l+r)>>1;
     63   if (loc <= mid) return query(o->child[0], l, mid, loc);
     64   else return query(o->child[1], mid+1, r, loc);
     65 }
     66 int find(node *o, int loc) {
     67   while (true) {
     68     int tmp = query(o, 1, n, loc);
     69     if (!tmp) return loc;
     70     loc = tmp;
     71   }
     72 }
     73 void work() {
     74   read(n), read(m);
     75   root[0] = pos;
     76   build(root[0], 1, n);
     77   for (int i = 1; i <= m; i++) {
     78     read(opt);
     79     if (opt == 1) {
     80       root[i] = root[i-1];
     81       read(a), read(b);
     82       a ^= lastans, b ^= lastans;
     83       int p = find(root[i], a);
     84       int q = find(root[i], b);
     85       if (p != q) {
     86     if (dep[p] == dep[q]) dep[p]++;
     87     else if (dep[p] < dep[q]) swap(p, q);
     88     update(root[i], 1, n, q, p);
     89       }
     90     }
     91     else if (opt == 2) read(a), a ^= lastans, root[i] = root[a];
     92     else {
     93       read(a), read(b);
     94       a ^= lastans, b ^= lastans;
     95       root[i] = root[i-1];
     96       int p = find(root[i], a);
     97       int q = find(root[i], b);
     98       if (p != q) printf("0
    "), lastans = 0;
     99       else printf("1
    "), lastans = 1;
    100     }
    101   }
    102 }
    103 int main() {
    104   work();
    105   return 0;
    106 }
  • 相关阅读:
    最大正数pascal程序
    部落卫队pascal解题程序
    使用递归和非递归遍历二叉树
    机器学习 Numpy库入门
    C++ 多态性和虚函数
    C++ 利用栈解决运算问题
    C++ 字符串分割
    C++继承与派生
    机器学习基础
    C++ 输出文件编码控制
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7628804.html
Copyright © 2020-2023  润新知