莫队

莫队
通过对询问排序,来优化暴力复杂度的离线算法。
还用到了分块的思想,不得不说分块思想的适用范围是真的广 ww
天依宝宝可爱!
SPOJ 3267 | 普通莫队
思维难度:\(\color{#F39C11} 橙\) *900
思想和分块有点类似。
首先考虑这样一个算法:首先维护一个桶,统计每个数的出现次数,每次完成了一个询问 \([l,r]\) 时,桶里面存的就是这个区间内的答案;假设现在要询问 \([l',r']\),那么可以考虑将当前区间先扩张在缩小(避免区间为空),这样就可以从 \([l,r]\) 延伸到 \([l',r']\)。
但是显然很容易卡掉,如果出现在序列两端反复横跳的询问就退化到 \(O(nq)\) 了。
为了避免,可以将询问离线并排序!
那么怎么排序呢?
首先如果直接按照 \(l\) 为第一关键字,\(r\) 为第二关键字的话,显然很容易卡的。
这时候就要用到分块的思想了,注意到我们是允许一个端点在小范围内任意移动的,这样不会使复杂度退化,所以考虑按照 \(l\) 所在的块为第一关键字,\(r\) 为第二关键字排序,这样对于同一个块内的 \(l\),最多操作 \(\frac n B \times B\) 次,\(r\) 最多 \(n\) 次,所以我们就得到了一个 \(O(\frac n B \times (\frac n B \times B + n))\) 的算法。
于是取 \(B = \sqrt n\),做完了。
天依宝宝可爱!
洛谷 P1494
思维难度:\(\color{#F39C11} 橙\) *900
和上一题真的有什么区别吗,需要维护的信息几乎是一样的。
天依宝宝可爱!
CF617E
思维难度:\(\color{#F39C11} 橙\) *1000
忘了异或可以前缀和了,糖丸了。
显然区间异或和可以转化成前缀异或和数组的单点异或和,然后就是板子了。
注意特判 \(k=0\),因为这会使 \(x \oplus k = x\),导致在删除的时候会多删一个。
莫队排序小技巧:奇数块按 \(r\) 升序,偶数块降序。
天依宝宝可爱!
洛谷 P3245
思维难度:\(\color{#FFC116} 黄\) *1400
首先可以转后缀和,设 \(s_i\) 为数位 \(i \sim n\) 组成的数模 \(p\) 的余数,那么一对 \(l,r\) 满足条件当且仅当:
然后这里有一个小 trick,记得梦熊练石有一个题用过来着。因为这个 \(\times 10^{n-r}\) 不怎么好处理,所以考虑消掉它,注意到当 \(p \nmid 10\) 时,\(10\) 的幂不会对结果产生任何影响,所以可以直接删掉,然后就变成了裸的后缀和了,显然就是莫队板子。当然还要考虑 \(p \mid 10\) 的情况,也就是 \(p = 2\) 或 \(5\),不过这是容易的,直接前缀和即可。
注意 \(p\) 的值域是 \(10^9\),所以 \(s\) 没法直接开桶计数,但是又因为 \(s\) 只有 \(n\) 个取值,所以离散化掉就可以了。不过直接上 umap 也能水过去。
天依宝宝可爱!
洛谷 P1903 | 带修莫队
思维难度:\(\color{#F39C11} 橙\) *1000
带修莫队。
显然朴素地维护 \(l,r\) 两个指针是不可以的,所以考虑再多加一个指针 \(t\) 表示当前进行了几次修改,可以发现 \(t\) 的伸缩是好维护的。
然后平衡复杂度,这里取块长 \(B = n^{\frac 2 3}\),那么就分为了 \(n^{\frac 1 3}\) 块。排序按照 \(l\) 所在的块为第一关键字,\(r\) 所在的块为第二关键字,\(t\) 为第三关键字。
于是 \(t\) 的总修改量显然是 \(O(n^{\frac 1 3})^2 \times O(n) = O(n^{\frac 5 3})\),考虑每一对 \(l,r\) 都会使 \(t\) 产生 \(O(n)\) 的移动量即可证明。然后是 \(l,r\) 的总修改量,但是我不会证。具体推导过程 OI-Wiki 有分析,需要求导。
冷知识:在调用函数的时候参数内部的修改会导致 UB,不过仅限于给同一个函数传参时多次用到 a 的情况。
总复杂度 \(O(n^{\frac 5 3})\)。
天依宝宝可爱!
CF940F
思维难度:\(\color{#FFC116} 黄\) *1200
显然还是维护桶,但是 mex 好像不怎么好维护。
不过我们发现,其实 mex 直接暴力就可以,因为当 mex 为 \(x\) 时,出现 \(1 \sim x-1\) 次的数都至少有一个,于是 mex 值最大只能为 \(\sqrt n\),所以算 mex 的总复杂度是 \(O(n \sqrt n)\) 的,小于莫队的复杂度。
不过如果非得优化,也是可以做的,套上一个分块或者线段树即可。
注意值域以及数组越界。
天依宝宝可爱!
AT_joisc2014_c | 回滚莫队
思维难度:\(\color{#F39C11} 橙\) *1000
上面写的莫队都是满足可插入可删除的,但是如果我们要做类似于 max 的东西,那就只可插入不可删除了,这时候还可以用莫队做吗?
于是就有了一种仅插入(或仅删除,两者等价)的莫队。
因为只可以插入,那就把 \(l\) 固定在 \(bl_l\) 的右端点上,然后 \(r\) 从左往右扩展(这里就不能奇偶优化了,因为必须保证 \(r\) 升序)。如果一个 \(r\) 对应的 \(l\) 不在 \(bl_l\) 的右端点上,那就先记录下当前的答案 \(x\),再把 \(l\) 往左扩展到指定位置,这样就得到了该询问的答案,然后再把 \(l\) 回退到 \(bl_l\) 的左端点(即把当前答案重置为 \(x\)),这样就在保证复杂度的同时避免了删除操作。
改一改就是这个题了。
注意上面的方法没法处理 \(bl_l = bl_r\) 的情况,不过这个直接暴力就可以。
天依宝宝可爱!
[补]洛谷 P5906
天依宝宝可爱!
[补]洛谷 P4887 | 二次离线莫队
天依宝宝可爱!
[补]洛谷 P5047
天依宝宝可爱!

浙公网安备 33010602011771号