套路的数据结构

1

给定长度为 \(n\) 的序列 \(a,b\)。两种操作:

  1. 询问区间 \([l,r]\),查询 \(\max\limits_{i=l}^{r}{\{a_i\times b_i\}}\)
  2. 给定 \(l,r,v\),区间 \(\forall i\in[l,r]\)\(b_i\gets b_i +v\)

分块。块长取 \(O(\sqrt n)\)

修改:整块维护块内最值、李超线段树(维护若干个斜率为 \(a_i\) 、截距为 \(a_i\times b_i\) 的直线)、加法 \(\text{tag}\)

整块:查询 \(x=(\text{tag}+v)\) 的极值,更新块内最值、\(\text{tag}\)

散块,pushdown 加法 \(\text{tag}\),重构该块。修改单次复杂度为 \(O(\sqrt n\log V)\)

查询:平凡。单次复杂度为 \(O(\sqrt n)\)

2

经典问题:给定长度为 \(n\) 的排列,初始为 \(1,2,\cdots, n\)。进行 \(m\) 次交换操作,每次操作完后询问排列的逆序对数量。CF785E

首先,将交换产生的影响转换:设交换 \([x,y]\),实际求区间 \([x+1,y-1]\)\(a_x > a_i\)\(a_x < a_i\)\(a_y > a_i\)\(a_y < a_i\) 的数量。

2.1

分块。设块长为 \(B\)。用值域树状数组维护块内信息。整块查询复杂度为 \(\mathcal{O}(\dfrac{n}{B}\log n)\),散块暴力 \(\mathcal O(B)\)。修改复杂度 \(\mathcal O(\log n)\)。根号平衡,当 \(B\)\(\Theta(\sqrt {n\log n})\) 时最优,时间复杂度为 \(\mathcal O(n\sqrt {n\log n})\),空间复杂度 \(\mathcal O(n\sqrt{\dfrac{n}{\log n}})\)

2.2

可以使用二分 + vector 替代树状数组,此时空间复杂度降为 \(\mathcal O(n)\),修改时间复杂度为 \(\mathcal O(\sqrt n)\),总时间复杂度不变。

2.3

优化。注意到,使用树状数组时维护时,修改复杂度 \(\mathcal O(\log n)\) 远低于查询复杂度 \(\mathcal O(\sqrt{n\log n})\),因此考虑改使用值域分块维护整块内信息。

具体而言,对于每块序列分块,维护每整块值域分块的前缀和,空间复杂度为 \(\mathcal O(n)\)。继续处理值域分块中散块的部分,对于每块序列分块,维护但块值域分块的前缀和,空间复杂度为 \(\mathcal O(n\sqrt n)\)

对于单个序列分块,先用第一个前缀和数组求出值域分块整块的结果,再用第二个前缀和数组求出值域分块散块的结果,此时单块查询复杂度为 \(O(1)\),总查询复杂度为 \(\mathcal O(\sqrt n)\)。修改则更新两个前缀和数组即可,复杂度为 \(O(\sqrt n)\),这样总时间复杂度为 \(O(n\sqrt n)\),用值域分块平衡了查询和修改。

2.4

进一步优化空间。注意到 \(a\) 为排列。对于值域分块的散块部分,最多存在 \(O(\sqrt n)\) 个数,因此这部分暴力枚举,通过维护值所在的位置查询即可,不需要维护前缀和,空间复杂度降为 \(O(n)\)

2.5

其他做法,树套树 / 分治。

posted @ 2023-10-04 22:25  sprads  阅读(30)  评论(0)    收藏  举报