3674: 可持久化並查集加強版
time limit: 15 sec memory limit: 256 mb
submit: 4051 solved: 1503
[submit][status][discuss]
description
description:
自從zkysb出了可持久化並查集後……
hzwer:亂寫能ac,暴力踩標程
kuribohg:我不路徑壓縮就過了!
ndsf:暴力就可以輕鬆虐!
zky:……
可持久化並查集… 其實我們發現每次合併如果按秩合併的話只會改變乙個點的fa, 那麼就好比主席樹每次有乙個點不同, 修改一條鏈. 那麼我們就可以用主席樹維護每個點的fa和每個點的rk(即按秩合併的rk). 按秩合併本身暴力爬樹是log, 每次查fa也變成log, 那麼就是log^2n的複雜度… 用主席樹維護即可.
用路徑壓縮有兩點不對:
1. 第i棵主席樹的建立由於路徑壓縮會改變多個點的fa, 那麼空間會增加很大一部分, 不像按秩合併只會改變乙個點的fa.
2. 多次合併, 每次合併乙個集合的root和乙個單點, 觸發find後等於無效. 這樣多次操作就成了一條長鏈… 成一條長鏈後那麼每次操作回到這個版本, 那麼路徑壓縮就會很長.
#include
#include
#define boc register char
#define acce register int
const int maxn = 2e5 + 5;
int n, m, ans;
inline const int
read()
struct node
pool[maxn * 50], *root[maxn], *tail = pool;
node* build(int lf, int rg)
int mid = (lf + rg) >> 1;
bt -> ls = build(lf, mid);
bt -> rs = build(mid + 1, rg);
return bt;
}void modify(node* &bt, node* pre, int lf, int rg, int
pos, int val)
int mid = (lf + rg) >> 1;
if(pos
<= mid) bt -> rs = pre -> rs, modify(bt -> ls, pre -> ls, lf, mid, pos, val);
else bt -> ls = pre -> ls, modify(bt -> rs, pre -> rs, mid + 1, rg, pos, val);
}node* query(node* bt, int lf, int rg, int
pos)
node* find(int u, int i)
int main()
if (opt == 2) u = read(), u ^= ans, root[i] = root[u];
if (opt == 3)
}}
bzoj 3674 可持久化並查集)
傳送門 題解 一道可持久化並查集的裸題,板子子對了就能過 可持久化並查集是基於主席數的一種結構,可持久化並查集要求能夠訪問歷史版本,跟主席樹很像,所以可以通過主席樹維護普通並查集的fa陣列,但是由於用主席樹維護後沒有辦法用路徑壓縮,所以需要採用新的合併方式 啟發式合併,對每乙個節點增加乙個level...
bzoj 3674 可持久化並查集加強版
description 自從zkysb出了可持久化並查集後 hzwer 亂寫能ac,暴力踩標程 kuribohg 我不路徑壓縮就過了!ndsf 暴力就可以輕鬆虐!zky bzoj 3673的加強版。就沒了。include using namespace std const int n 200000 ...
BZOJ 3674 可持久化並查集加強版
題意 三種操作 1 合併ab所在集合 2 查詢ab是否在乙個集合 3 狀態回到第x個操作之前。思路 1 每個節點儲存乙個深度 合併時找到兩個節點的根,ra,rb,若ra的深度小,則ra的父親設為rb,否則rb的父親設為ra 2 查詢直接找到兩個的根。這個的複雜度是多少呢?貌似是logn logn。每...