线段树的进阶操作

写在前面

感觉线段树的一些拓展比较有意思,整理一下。

参考资料:关于线段树上的一些进阶操作 - 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\)。第一个维护显然,主要是第二个。

\[\begin{align*}\Delta ms_3&=\sum\limits_{i=1}^{m_3} [q_3[i]=upd] S_3[i]\\&=\sum\limits_{i=1}^{m_1}[q_1[i]=upd]S_1[i]+\sum\limits_{i=1}^{m_2} [q_2[i]=upd] S_1[m_1]+S_2[i] \end{align*} \]

历史最值

原理

当前最大值为 \(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]\)

\[S_3[i]=\begin{cases}S_1[i]&(1\leq i\leq k_1)\\S_1[k_1]+S_2[i-k_1]&(k_1+1\leq i\leq k_1+k_2)\end{cases} \]

也就是说 \(\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

历史最值不能将两种操作混在一起。除了区间赋值外,几乎就是模板。考虑如何维护区间赋值。发现在区间赋值之后的区间加法可以转化为区间赋值,那么原来的操作序列就是一段加法,一段赋值。不难维护。

posted @ 2023-06-24 15:32  starrylasky  阅读(17)  评论(0)    收藏  举报