BZOJ 3674 可持久化並查集

2021-08-11 06:58:22 字數 1600 閱讀 3466

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。每...