莫队


莫队

通过对询问排序,来优化暴力复杂度的离线算法。

还用到了分块的思想,不得不说分块思想的适用范围是真的广 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\),做完了。

submission

天依宝宝可爱!


洛谷 P1494

思维难度:\(\color{#F39C11} 橙\) *900

和上一题真的有什么区别吗,需要维护的信息几乎是一样的。

submission

天依宝宝可爱!


CF617E

思维难度:\(\color{#F39C11} 橙\) *1000

忘了异或可以前缀和了,糖丸了。

显然区间异或和可以转化成前缀异或和数组的单点异或和,然后就是板子了。

注意特判 \(k=0\),因为这会使 \(x \oplus k = x\),导致在删除的时候会多删一个。

莫队排序小技巧:奇数块按 \(r\) 升序,偶数块降序。

submission

天依宝宝可爱!


洛谷 P3245

思维难度:\(\color{#FFC116} 黄\) *1400

首先可以转后缀和,设 \(s_i\) 为数位 \(i \sim n\) 组成的数模 \(p\) 的余数,那么一对 \(l,r\) 满足条件当且仅当:

\[p \mid (s_l - s_{r+1}) \times 10^{n-r} \]

然后这里有一个小 trick,记得梦熊练石有一个题用过来着。因为这个 \(\times 10^{n-r}\) 不怎么好处理,所以考虑消掉它,注意到当 \(p \nmid 10\) 时,\(10\) 的幂不会对结果产生任何影响,所以可以直接删掉,然后就变成了裸的后缀和了,显然就是莫队板子。当然还要考虑 \(p \mid 10\) 的情况,也就是 \(p = 2\)\(5\),不过这是容易的,直接前缀和即可。

注意 \(p\) 的值域是 \(10^9\),所以 \(s\) 没法直接开桶计数,但是又因为 \(s\) 只有 \(n\) 个取值,所以离散化掉就可以了。不过直接上 umap 也能水过去

submission

天依宝宝可爱!


洛谷 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 的情况。

  • upd(p[++T].p,p[T].c) WA
  • ++T,upd(p[T].p,p[T].c) AC

总复杂度 \(O(n^{\frac 5 3})\)

submission

天依宝宝可爱!


CF940F

思维难度:\(\color{#FFC116} 黄\) *1200

显然还是维护桶,但是 mex 好像不怎么好维护。

不过我们发现,其实 mex 直接暴力就可以,因为当 mex 为 \(x\) 时,出现 \(1 \sim x-1\) 次的数都至少有一个,于是 mex 值最大只能为 \(\sqrt n\),所以算 mex 的总复杂度是 \(O(n \sqrt n)\) 的,小于莫队的复杂度。

不过如果非得优化,也是可以做的,套上一个分块或者线段树即可。

注意值域以及数组越界。

submission

天依宝宝可爱!


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\) 的情况,不过这个直接暴力就可以。

submission

天依宝宝可爱!


[补]洛谷 P5906

天依宝宝可爱!


[补]洛谷 P4887 | 二次离线莫队

天依宝宝可爱!


[补]洛谷 P5047

天依宝宝可爱!

posted @ 2025-08-19 09:39  little__bug  阅读(7)  评论(0)    收藏  举报