分块算法的简单应用
莫队
莫队是分块的一个应用,即对询问分块。
思想:
- 通过移动端点的方式将一个询问转移至另一个,从而减少重复计算。
- 对询问分块排序以平衡左右端点移动复杂度。
过程:
- 将序列分成若干块,然后将询问离线;
- 以左端点所属块的编号为第一关键字,右端点位置为第二关键字进行排序;
- 每次通过扩张/删除左右端点的操作将左右端点转移至当前询问,更新答案。
条件
- 支持离线
- 可以\(\Omicron(1)\)(或是较小复杂度)移动端点(包括修改状态和更新答案两部分的复杂度)
莫队时间复杂度分析
当\(n,m,\)同阶时,\(k\)维莫队复杂度易证为\(n^{\frac{k-1}{k}}\).
二维莫队:
当扩展到更高维的情况时,假设除\(m\)外所有维度大小均为\(n\).
三维莫队(带修莫队):
归纳以上过程可得出:
带修莫队(单点修改)
考虑将时间作为第三维直接转换为三维莫队处理即可。
回滚莫队
如果支持快速扩张而不支持快速删除,可以使用回滚莫队。
过程
-
对于左右端点在一块内的询问,直接暴力处理。
-
首先将每个块对应的询问单独处理,这样只有左端点的右移需要删除。
-
初始时左端点位于块的最右端点,考虑每次移动后暴力将左端点造成的所有更新和贡献撤销,使得左端点回到原位置,以规避删除操作。
复杂度和其他过程同普通莫队。
条件
- 虽然不能快速删除,但是可以快速撤销,或是可以方便的保存原状态。
比如插入复杂度需要均摊的情况就可能因为撤销操作而导致错误。
特殊情况
有些时候不能插入,但可以快速删除,也能用相似的方法进行处理。
莫队二次离线
在移动端点时,可以膜拜\(\operatorname{\color{black}{M}\color{red}{YY}}\)!
有些情况下在移动端点时,可以做到\(\Omicron(1)\)查询,却只能\(\Omicron(k)\)修改,那么利用二次离线可以将整体复杂度优化至\(\Omicron(nk+n\sqrt n)\).
核心思想是将端点的移动再次离线,然后扫描线统计答案。
我们考虑当右端点移动时产生的贡献:
设\(\operatorname{f}(x,[l,r])\)为\(x\)对\([l,r]\)的贡献。
假设原先的区间为\([l,r]\),移动至\([l,k]\),考虑差分统计其中某个点\(x\in[r+1,k]\)的贡献:
观察到式子左边只\(x\)有关,可以预处理。
式子右边\(x\)的取值是连续的所以这样处理:
- 直接记录区间\([r+1,k]\),离线。
- 从左到右扫描,更新当前位置信息。
- 当扫描到\(l-1\)时,暴力扫描区间\([r+1,k]\)中的每个数统计贡献。
- 注意到\(\operatorname{f}(x,[1,l-1])\)不仅对当前区间有贡献,对之后的区间也有贡献,因此把他映射到询问数组上做一趟前缀和。
接下来考虑情况类似的左端点移动:
原区间\([l,r]\),移动至\([k,r]\),点\(x\in[k,l-1]\)的贡献:
我们可以如法炮制,预处理式子右边,扫描统计式子左边。
时间复杂度\(\Omicron(nk+n\sqrt n)\),空间复杂度\(\Omicron(n)\).
例题
luogu4887 第十四分块(前体)
考虑直接普通莫队,开个桶,莫队,每次修改的时候把所有和自己\(\operatorname{xor}\)结果有\(k\)个\(\textbf{1}\)的位置加上1,每次修改最多需要高达\(\binom{14}{7}=3432\)次操作,但是查询的复杂度只有\(\Omicron(1)\),因此使用二次离线。
注意到这题里面一个数是不能和自己产生贡献的,所以\(\operatorname{f}(x,[1,x])\)直接拿\(\operatorname{f}(x,[1,x-1])\)代替,最后再特判即可。
时间复杂度\(\Omicron(3432n+n\sqrt n).\)
莫队的一个经典应用
多询问组合数前缀和
令
\[\operatorname{F}(n,m)=\sum_{k=0}^{m}\binom{n}{k} \]询问\(T\)次\(\operatorname{F}(n,m)\),\(n,m,k\)同阶。
利用加法恒等式(\(\binom{n+1}{k}=\binom{n}{k}+\binom{n}{k-1}\))可以将\(n,m\)在\(\Omicron(1)\)的时间内移动,于是就能利用三维莫队以\(\Omicron(n^{\frac{2}{3}})\)的复杂度规划出一条路径。

浙公网安备 33010602011771号