基于分块优化的暴力。
离线算法,适用于能够快速加减单点的贡献的区间询问。
普通莫队
板子题:P1494 「国家集训队」小Z的袜子 或者:P2709 小B的询问。
给出长为
的序列 ,每次询问区间内 。
从暴力开始优化:
一个区间询问可以移动左右端点来得到另一个区间询问的答案,从而避免重复计算两个区间重叠的部分,那就设两个指针
但还是会被卡成
于是将询问
将序列分块,
复杂度
对于
对于
不考虑计算答案复杂度,这样莫队的总体复杂度就是
奇偶性优化
为了衔接相邻两个块的
树上莫队
SP10707 COT2 - Count on a tree II
给定
个结点的树,每个结点有一种颜色, 次询问,每次询问 之间的路径上的结点的不同颜色数。
, 。
把树转化成括号序,就是序列问题了,设
为 的祖先,查询 中所有出现 次的点的答案;- 否则,查询
的所有出现 次的点的答案,记得单独处理 。
通过重链剖分可以轻松得到
带修莫队
相对于普通莫队多了修改操作。
同样是把左右操作离线,分开询问和修改,并都打上时间戳。
可以想到多设一个指针在
发现这样单次会被卡成
调整排序方法
- 第一关键字:
所在块; - 第二关键字:
所在块; - 第三关键字:时间戳。
这样
调整块的大小
设修改操作序列长为
证明见 Minclxc 的博客。
懒得话实测
回滚莫队
给出长为
的序列 , 为 中 出现的次数,每次询问区间内 。
发现由于
只能加点不能删点,这时候回滚莫队就出现了。
还是先套路地分块,像普通莫队一样排序(不加奇偶性优化)。
同一个块里的询问右端点单调递增,满足只加不减。
发现左端点在块里反复横跳,干脆每次都从块的右端向左扩展,这样总复杂度仍然控制在
好了,现在有了完整的思路:
为了方便,将询问按左端点所在块分组,组内排序。
注意要将左右端点在同一块的询问单独处理。
对于每一个块内,设指针
二次离线莫队
给了你一个序列
,每次查询给一个区间 查询 且 的二进制表示下有 个 的二元组 的个数。
。
莫队需要考虑怎么从
设
考虑差分,以从
所以就把对 vector
上,莫队之后从前到后扫,就类似扫描线一样处理。
其它的三种情况类似。
具体的预处理方法,运用异或运算的性质:
并且每次将
这题有个坑点:
总结一下,二次离线就是在莫队时,通过扫描线一类的方法,将需要更新的答案再次离线处理。
一些题目
-
树上莫队 + 带修莫队。
二合一,没啥,就是不太好码。
咕~
v1.5.2