莫队学习笔记

1|0莫队

莫队是一种常见的离线处理区间查询问的方法。

莫队的思想是把序列分块,然后把询问按照左端点所在块为第一关键字,右端点为第二关键字排序,然后处理询问,维护指针 l,r 表示当前处理的区间是 [l,r],每次根据询问区间来移动指针计算贡献。

关于复杂度。假设指针移动的复杂度是 O(p),设块长为 B,那么就有 nB 块。每个询问左端点最多移动 B 次,每一块的询问右端点最多移动 n 次,于是总移动次数就是 O(qB+n2B),当 Bnq 就可以做到 O(nqp)

关于常数,莫队的常数很小,而且可以用奇偶分块减小一半的常数。

1|1P1972 [SDOI2009] HH的项链

题意:区间数颜色。

思路:把询问离线,然后跑莫队,用一个数组维护当前区间内每个数的出现次数,移动指针时,如果是加入一个数且这个数的出现次数是 0,就说明颜色数增加了 1;如果删除一个数且删除后出现次数为 0,那么颜色数就减少了 1。

1|2「JOISC 2014 Day1」历史研究

题意:有序列 a,多次询问区间 [l,r]ai×cnt[ai] 的最大值,其中 cnt 表示区间内出现次数。

思路:回滚莫队模板题。

首先考虑用莫队,但是我们发现在删除时不好维护最大值,那就想办法不删除,这就是回滚莫队。具体地,对于莫队指针的左右端点,右端点还是和普通莫队一样,每次往右移,然后记录下当前值。左端点就不太一样了,每处理完一次询问就回到左端点所在的段的末尾,然后令答案回到之前记录的值,这样就可以保证在不删除的情况下答案正确。

1|3P4887 【模板】莫队二次离线(第十四分块(前体))

题意:求区间中两个数异或值中有 k 个 1 的数对个数。

思路:莫队二次离线。

以前因为莫队二离是个很高端的东西,现在来看发现还好。

本质是把莫队端点移动时查询答案的操作再离线一遍,然后用一遍扫描线来计算。难点在于这样拆出来的询问有 O(nn) 的,需要进一步优化。

以右端点的移动为例,假设右端点从 rr+k,那么我们要计算的就是 x=r+1r+kf(x,[l,x1]),我们发现这个贡献是可差分的,于是就变成了 x=r+1r+kf(x,[1,x1])f(x,[1,l1]),对于左边,这个值是可以预处理的,而后面就是 [1,l1][r+1,r+k] 的贡献,可以用扫描线计算,这样我们就只有 O(n) 个询问了。

1|4P3674 小清新人渣的本愿

题意:求区间是否可以选择两个数满足加和/差/乘积为 x

思路:分开维护

对于“+”“-”,可以直接莫队维护区间值域 bitset。

对于“*”,可以直接枚举因数,再判断是否有 i,ci 同时存在。

1|5P4688 [Ynoi2016] 掉进兔子洞

题意:求 3 个区间的交的大小。

思路:做法还好,但是很难写。

首先,容易想到莫队 +bitset,但是这道题中同颜色可以有多个,不能直接用 bitset,要给每个颜色预留这个颜色大小的区域。

然后就是空间问题,需要把询问分3组来卡空间。

1|6P4689 [Ynoi2016] 这是我自己的发明

题意:换根,求给出 x,y,从 x,y 的子树里各选一个点满足点权相等的方案数。

思路:首先,如果在 dfn 序上进行操作,那么每个点的子树就对应着1或2个区间。

f(l,r,L,R) 为第一个区间为 [l,r],第二个区间为 [L,R] 的答案,这样状态是4维的,而这个信息显然是可以差分的,于是考虑怎么拆贡献。

考虑两种极端的情况,f(l,r,1,L1)+f(l,r,R+1,n)f(1,l1,1,L1)+f(1,l1,R+1,n)+f(r+1,n,1,L1)+f(r+1,r,R+1,n),可以拆成 f(l,r,1,n)f(l,r,L,R)f(1,n,1,n)f(l,r,1,n)f(L,R,1,n)+f(l,r,L,R),都转成了只有 f(l,r,L,R) 的情况,于是就好处理了。

转成差分后,就可以用莫队来求出每个区间的答案了。

1|7P8078 [WC2022] 秃子酋长

题意:求区间排序后相邻的数在原序列中的位置的差的绝对值之和。

思路:终于来写秃子酋长了,上次看还是在WC的时候。

其实就是只删除莫队的板子。

考虑莫队,那么如果用常规莫队写法的话,加入一个点是 O(logn) 的,那么就会让复杂度变为 O(nnlogn),考虑怎么优化。我们发现,如果我们预先处理好了每个数应该在什么位置,然后建链表,这样删除就只有 O(1) 了。

其实跟回滚莫队是差不多的。

1|8P9340 [JOISC 2023 Day3] Tourism

题意:给出一颗 n 个节点的树,和一个长度为 m 的序列 aq 次询问包含 alr 中所有节点的最小联通块大小。

思路:做了秃子酋长才发现这题好板。

用只删除莫队,然后按 dfn 序排序后建链表,再加上 O(1)LCA 就可以了。


__EOF__

本文作者Xttttr
本文链接https://www.cnblogs.com/Xttttr/p/18015275.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Xttttr  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示