可持久化並查集加強版 BZOJ 3674

2022-05-03 21:54:16 字數 2673 閱讀 4144

time limit: 15 sec  memory limit: 256 mb

submit: 3225  solved: 1192

[submit][status][discuss]

5 61 1 2

3 1 2

2 13 0 3

2 13 1 210

1如何構造乙個可持久化並查集呢?我們知道並查集是由陣列實現的,所以只要能寫出可持久化陣列,自然就能寫出可持久化並查集了。查了一些資料,可持久化陣列似乎就是可持久化線段樹(這個我也不太確定),但是我們還是可以用線段樹代替一下陣列實現並查集,我們只需要線段樹的葉節點去合併就可以了,實際上線段樹上面的區間都是沒什麼用的,但是又不能刪掉,因為我們還要維護root[i]。同時要注意並查集合並的時候不要路徑壓縮,因為壓縮後會影響太多點,返回歷史版本會很難,所以我們選擇人畜無害的按秩合併,同樣可以快到飛起。具體實現看**吧。可持久化並查集可以用pb_ds庫的rope,現成模板,我也貼乙份模板在下面了,不過這個跑起來的時間是自己寫的版本的兩倍。(ps:其實是可以進行路徑壓縮的,但是空間要稍微開大一點)

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define x first

#define y second

#define clr(u,v); memset(u,v,sizeof(u));

#define in() freopen("data","r",stdin);

#define out() freopen("ans","w",stdout);

#define clear(q); while (!q.empty()) q.pop();

#define pb push_back

using

namespace

std;

typedef

long

long

ll;typedef pair

pii;

const

int maxn = 2e5 + 10

;const

int inf = 0x3f3f3f3f

;struct

tree

t[maxn

<<5

];int root[maxn], cnt = 0

;int deep[maxn];//

並查集深度

intn, m;

void build(int l, int r, int &x)//

先建樹,進行初始化,如果有多case記得cnt初始化為0

int mid = (l + r) >> 1

; build(l, mid, t[x].l);

build(mid + 1

, r, t[x].r);

}int query(int l, int r, int rt, int pos)//

int find(int x, int cur)//

並查集的找祖先

void update(int l, int r, int &x, int y, int pos, int

fa)

int mid = (l + r) >> 1

;

if (mid >=pos) update(l, mid, t[x].l, t[y].l, pos, fa);

else update(mid + 1

, r, t[x].r, t[y].r, pos, fa);

}void mix(int x, int y, int

cur)

intmain()

else

if (op == 2

)

else

}return0;

}

pb_ds庫的rope:

#include #include 

#include

using

namespace

std;

using

namespace

__gnu_cxx;

const

int maxn = 2e5 + 10

;rope

*f[maxn];

rope

:: iterator it;

intid[maxn];

intn, m, op, a, b;

int find (int &t, int

x)void mix(int &t, int x, int

y)int lastans = 0

;int

main()

else

if (op == 2

)

else

if (op == 3

)

}return0;

}

int find(int x, int cur)//並查集的找祖先

return t[pos].fa;

}

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

bzoj3674 可持久化並查集加強版

3674 可持久化並查集加強版 description description 自從zkysb出了可持久化並查集後 hzwer 亂寫能ac,暴力踩標程 kuribohg 我不路徑壓縮就過了 ndsf 暴力就可以輕鬆虐 zky n個集合 m個操作 操作 1 a b 合併a,b所在集合 2 k 回到第k...