线段树分裂
线段树合并
【线段树合并板子】
线段树分裂
将以 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\) 小的概率。
\[f(u,i)=\\
f(ls[u],i)*\left(p_u\sum_{j=1}^{i-1}f(rs[u],j)+(1-p_u)\sum_{j=i+1}^mf(rs[u],j)\right)
\\
+
\\
f(rs[u],i)*\left(p_u\sum_{j=1}^{i-1}f(ls[u],j)+(1-p_u)\sum_{j=i+1}^mf(ls[u],j)\right)
\]
用线段树合并解决。
【记录】