datastructure杂记

发布时间 2023-11-03 18:38:18作者: Kun_9

线段树

线段树合并&&分裂

可持久化线段树

线段树分治

Seg—beats

兔队线段树

历史最值&&历史版本和

Q:维护一种数据结构,支持对数列 \(\{a\},\{b\}\) 的如下操作

  • \(\{a\}\) 区间加,之后令 \(b_i\leftarrow \max(b_i,a_i)\)
  • 历史最大值,求 \(\max(b_{l\cdots r})\)

采用打标记的方式处理修改操作,考虑标记下放的操作对 \(b\) 序列的影响。

我们先不合并标记,设当前节点上的所有标记按下放顺序形成了一个队列 \(q\)

为了方便这里约定 \(s[i]\) 表示到 \(i\) 之前所有加标记的前缀和,\(add\) 为加标记,\(hadd\) 为所有加标记中的最大值,\(mx\) 为当前最大值,\(hmx\) 为历史最大值。

对于核心操作 pushdown,我们把自己(now)的标记队列为 \(q_1\),父亲的标记队列为 \(q_2\),合并后的标记队列为 \(q_3\)

考虑对历史最值的贡献:

\[\begin{split} hmx_3 &= mx_3 + \max_{i=1}^{|q_3|}s_3[i]\\ &=mx_3 + hadd_3 \end{split} \]

考虑对历史最大加标记的贡献:

\[\begin{split} hadd_3 &= \max_{i=1}^{|q_3|}s_3[i]\\ &= \max\{\max_{i=1}^{|q_1|}s_1[i],\max_{i=1}^{|q_2|}s_2[i]+s_1[|q_1|]\}\\ &= \max\{hadd_1,hadd_2+add_1\} \end{split} \]

历史和

Q:维护一种数据结构,支持对数列 \(\{a\},\{b\}\) 的如下操作

  • \(\{a\}\) 区间加,之后令 \(b_i\leftarrow b_i+a_i\)
  • 历史和,求 \(\sum_{i=l}^r b_i\)

同样打标记处理,为了能更新,不妨把 \(b\) 序列的更新也作为一个标记 \(upd\)

\(cnt\) 为队列中更新标记的个数, \(sum\) 为当前节点的区间和, \(hsum\) 为当前节点的历史和,\(add\) 为当前节点的加标记,\(hadd\) 为当前节点加标记的历史和,\(s[i]\) 为加标记的前缀和。

考虑标记对历史和的贡献:

\[\begin{split} hsum &= \sum_{i = 1}^{|q|}[q[i] = upd](sum+s[i]*len)\\ &=sum*cnt + len*hadd \end{split} \]

考虑合并两个队列:

\[\begin{split} hadd_{now} &= \sum_{i=1}^{|q_1|+|q_2|}[q_3[i] = upd]s_3[i]\\ &= \sum_{i = 1}^{|q_1|}[q_1[i] = upd]s_1[i] + \sum_{i = 1} ^{|q_2|}[q_2[i] = upd](s_1[|q_1|]+s_2[i])\\ &= hadd_1+add_1*cnt_2+hadd_2 \end{split} \]

复杂信息维护