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