BZOJ 3674 可持久化並查集加強版(主席樹變形)
阿新 • • 發佈:2017-05-24
als ret desc scan sync scanf ops 只需要 ica
Submit: 2515 Solved: 1107
[Submit][Status][Discuss]
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
0
1
3673: 可持久化並查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 2515 Solved: 1107
[Submit][Status][Discuss]
Description
n個集合 m個操作
操作:
1 a b 合並a,b所在集合
2 k 回到第k次操作之後的狀態(查詢算作操作)
3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0
0<n,m<=2*10^4
Input
Output
Sample Input
5 61 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
10
1
HINT
Source
出題人大SB
題目鏈接:BZOJ 3674
原來並查集也是可以可持久化的,其思想應該是在於用可持久化數據結構來維護一個前綴記錄,由於普通的並查集一開始每一個節點的祖先都是本身,因此要多一個建樹的操作,把所有的葉子節點的祖先都處理好,然後這題是並查集,並不需要差分的思想,也就是說更新或者查詢只需要用到一個root點, 其他的做法跟普通的並查集差不多,詳細的可以看黃大牛的博客:http://hzwer.com/3997.html。
代碼:
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); typedef pair<int, int> pii; typedef long long LL; const double PI = acos(-1.0); const int N = 2e5 + 7; struct seg { int lson, rson; int pre; }; seg T[N * 40]; int root[N], tot; int n; void init() { CLR(root, 0); tot = 0; } void build(int &cur, int l, int r) { cur = ++tot; T[cur].lson = T[cur].rson = 0; if (l == r) T[cur].pre = l; else { int mid = MID(l, r); build(T[cur].lson, l, mid); build(T[cur].rson, mid + 1, r); } } void update(int &cur, int ori, int l, int r, int pos, int pre) { cur = ++tot; T[cur] = T[ori]; if (l == r) { T[cur].pre = pre; return ; } else { int mid = MID(l, r); if (pos <= mid) update(T[cur].lson, T[ori].lson, l, mid, pos, pre); else update(T[cur].rson, T[ori].rson, mid + 1, r, pos, pre); } } int query(int k, int l, int r, int pos) //返回子節點位置 { if (l == r) return k; else { int mid = MID(l, r); if (pos <= mid) return query(T[k].lson, l, mid, pos); else return query(T[k].rson, mid + 1, r, pos); } } int Find(int k, int pre) { int idx = query(k, 1, n, pre); if (pre == T[idx].pre) return pre; else return Find(k, T[idx].pre); } int main(void) { int m, i, a, b, k, ops; while (~scanf("%d%d", &n, &m)) { init(); int ans = 0; build(root[0], 1, n); for (i = 1; i <= m; ++i) { scanf("%d", &ops); if (ops == 1) { scanf("%d%d", &a, &b); a ^= ans; b ^= ans; root[i] = root[i - 1]; int fa = Find(root[i], a); int fb = Find(root[i], b); if (fa != fb) update(root[i], root[i - 1], 1, n, fb, fa); } else if (ops == 2) { scanf("%d", &k); k ^= ans; root[i] = root[k]; } else if (ops == 3) { scanf("%d%d", &a, &b); a ^= ans; b ^= ans; root[i] = root[i - 1]; int fa = Find(root[i], a); int fb = Find(root[i], b); printf("%d\n", ans = (fa == fb)); } } } return 0; }
BZOJ 3674 可持久化並查集加強版(主席樹變形)