[BZOJ 3674]可持久化并查集加强版
Posted NaVi_Awson
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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
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\n"), lastans = 0; 99 else printf("1\n"), lastans = 1; 100 } 101 } 102 } 103 int main() { 104 work(); 105 return 0; 106 }
以上是关于[BZOJ 3674]可持久化并查集加强版的主要内容,如果未能解决你的问题,请参考以下文章