線段樹合併
【線段樹合併板子】
線段樹分裂
將以 x 爲根的線段樹分裂成 x,y 爲根的兩顆線段樹, 前 k 小在 x, 之後的在 y。
void split (int x, int & y, int k) {
y = newnode();
int v = val[ch[x][0]];
if (k > v)
split (ch[x][1], ch[y][1], k - v);
else {
swap (ch[x][1], ch[y][1]);
if (k < v)
split (ch[x][0], ch[y][0], k);
}
val[y] = val[x] - k;
val[x] = k;
}
【板子記錄】
HEOI2016/TJOI2016 排序
線段樹合併/分裂解決區間排序問題。
某種維護區間染色的方法(類似 Old Driver Tree)
// 使用 set 維護數列 1~n
// 區間 [l,r] 只在 set 保留 l
// n + 1 作爲哨兵
for (int i = 1; i <= n + 1; ++ i)
set.insert (i);
// split (i) 操作, 操作後保證 i 是某個區間的開頭,
iterator split (int p) {
iterator i = lower_bound (p);
if (*i == p) return i;
// 在這裏進行某些操作來維護區間
return set.insert (p).first;
}
// 把區間 [l,r] 染色
void gao (int l, int r) {
iterator il = split (l), ir = split (r + 1);
// 在這裏進行某些操作來維護區間
t.erase (++ il, ir);
}
【記錄】
PKUWC2018 Minimax
設 \(f(u,i)\) 爲節點 \(u\) 是第 \(i\) 小的概率。
用線段樹合併解決。
【記錄】