基本莫队
询问离线,按块排序,\(\sqrt n\) 分块,两个指针来回扫。
总时间复杂度为 \(\Theta(n\sqrt n)\)。
带修莫队
考虑增加一维时间戳(当前修改次数)。
在原有基础上,若左右端点在同一块内,按照时间戳排序。
注意每次处理到一个修改操作之后要取反。
块长取 \(n^{2 \over 3}\),总时间复杂度为 \(\Theta(n^{5\over 3})\)。
树上莫队
例题
将上的路径转为欧拉序,变成一段区间。
其他的与上面两种类似。
回滚莫队
例题
有时候对于区间取 min
与取 max
操作很难缩小区间,但容易扩大区间,考虑回滚莫队。
与普通莫队一样,先排序(右端点升序)。
先将左右端点同块的区间暴力求解。
对于左右端点不同块的,右端点可以一直向后走(升序),左端点对于每一次询问,从当前块的右端点重新开始枚举,向左拓展。
右端点移动是 \(\Theta(n)\) 的,共 \(\sqrt n\) 次,左端点移动是 \(\Theta(\sqrt n)\)的,共 \(n\) 次,暴力是 \(\Theta(n \sqrt n)\) 的。
故总时间复杂度是 \(\Theta(n \sqrt n)\)。
莫队二次离线
例题
对于一些可以莫队,但更新答案的时间不是 $\Theta(1) $ 的题目可以用二次离线。
考虑每次指针移动带来的贡献,设变化为 \([l,r] \to[l,r+k]\)。
统计 \(\forall x \in [r+1,r+k]\) 对于 \([l,x-1]\) 的贡献。
先差分一下,变成 \(f([1,x-1])-f(1,l)\) 的贡献,左端点的移动也是类似的,变成\(f([1,r])-f([1,x-1])\)。
对于形如 \(x\) 对 \([1,x-1]\) 的贡献可以预处理,在莫队移动端点时直接记入答案。现在考虑怎么处理形如 \(x\) 对 \(f([1,l])\) 的贡献。
考虑将它们离线下来,用类似扫描线的做法维护
发现对于很多询问,它们的 \([1,l]\) 的 \(l\) 是形似的。考虑把它们记在 \(l\) 下。现在我们用 \(\Theta(n\sqrt n)\) 的询问和 \(\Theta(n)\) 的修改,所以需要一种 \(\Theta(\sqrt n)\) 修改 \(\Theta(1)\) 的查询的算法。
一般采用用分块维护前缀的大块信息与小块信息
总时间复杂度 \(\Theta(n\sqrt n)\),空间复杂的 \(\Theta(n)\)