线段树的进阶操作
写在前面
感觉线段树的一些拓展比较有意思,整理一下。
参考资料:关于线段树上的一些进阶操作 - command_block 的博客。
李超线段树
原理
两条线段 \(a,b, x \in [l,r]\),要么 \(a \cap b=\empty\),全取 \(a\),要么 \(|a \cup b|=1\),一段前缀取 \(a\)。所以每次将 \(c\) 与 \(\text {mid}\) 处最优线段比较,将 \(c\) 往更优地方下放。由于 \([l,r]\) 不一定在树上有对应的点,所以拆成 $\log n $ 个集合,时间复杂度 \(\log ^2 n\)。
兔队线段树
原理
将 \(\rm pushup,\log n\) 化,时间复杂度 \(\log^2 n\)。
例题
\(\text{I.}\)CF671E
显然的想法:二分答案,\(n^2\) 判断。
题解 ,尝试将条件代数化,在此基础上维护,似乎没有用到这个思想,但是好像有这个思想的解法。
历史版本和
记原序列 \(A\),版本和 \(B\),区间和 \(s\),历史版本和 \(ms\),区间长度 \(len\)。
加法:\(s+=t\cdot len\),更新:\(ms+=s\)。
考虑操作序列 \(q[1\cdots m]={t_1,t_2,upd,\cdots},S_i\) 表示加法标记前缀和。
\(ms+=s\sum\limits_{i=1}^m[q_i=upd]+len\cdot \sum\limits_{i=1}^m[q_i=upd]S_i\),所以只需维护两个 \(\sum\),这个不难维护。
考虑如何合并两个标记序列 \(q_1,q_2\),令合并后的为 \(q_3\)。第一个维护显然,主要是第二个。
历史最值
原理
当前最大值为 \(a\),历史最大值为 \(b\)。
一个加法序列 \(q[1 \cdots k]\),前缀和为 \(S[1 \cdots k]\)。在操作之后 \(a+=S_k,b+=\max(0,\max\limits_{i=1}^k{S_k})\)。所以只需要记录 \(\max\limits_{i=1}^k S_k\)。
考虑合并标记,加法很显然重要的是维护后面那个。
两个操作序列 \(q_1[1 \cdots k_1],q_2[1 \cdots k_2]\),前缀和为 \(S_1[1 \cdots k_1],S_2[1 \cdots k_2]\)。
也就是说 \(\max\limits_{i=1}^{k_1+k_2}=\max(\max\limits_{i=1}^{k_1} S_1,S1[k_1]+\max\limits_{i=1}^{k_2} S2)\)。
例题
\(\text{I.}\) P4314
历史最值不能将两种操作混在一起。除了区间赋值外,几乎就是模板。考虑如何维护区间赋值。发现在区间赋值之后的区间加法可以转化为区间赋值,那么原来的操作序列就是一段加法,一段赋值。不难维护。

浙公网安备 33010602011771号