当前位置: 首页 > news >正文

莫队

Argvchs 说我不会根号算法,把之前的博客搬过来,然后再补点东西。

一种离线算法,可以用 \(O(n\sqrt n)\) 的复杂度处理区间查询问题,当然,也可以带修,下文也会提到。

关于复杂度

莫队优化的关键是排序 + 分块,将每个询问离线下来,按照左端点所在块从小到大排序,假如左端点在同一个块,按照右端点从小到大排序。

处理问题时,我们可以通过移动左右端点来不断更新区间答案,而且排序后前后两个左端点的距离(移动次数)不会超过 \(2\times \sqrt n\) 次,总共 \(n\) 个查询,复杂度相乘也就是 \(O(n\sqrt n)\)。而因为右端点无序,但是固定左端的情况下按升序排列,所以因为左端有 \(O(\sqrt n)\) 块,而右端点一次移动 \(O(n)\) 次,总的也就是 \(O(n \sqrt n)\)。所以,莫队算法的总复杂度就是 \(O(n\sqrt n)\)

其实,这种排序方式并不是最优解,最优解应该按照曼哈顿距离建最小生成树,但因为本身写这个就是暴力算法,这个也就无所谓了。

一种优化方式,奇偶性排序。在移动莫队指针的过程中,两个询问之间左右移动,可能会出现多余移动的情况,那么我们可以按照奇块正序,偶块反序的方式来排序,可以优化 30% 左右。

P1972 HH的项链

模板,开桶维护区间数个数,虽然加强了数据,卡卡也是能过的。

Submission

P1494 小 Z 的袜子

假设有 \(k\) 个相同的数,那么会有 \(\left (_{2}^{k} \right )\) 种选法,总共 \(\sum \left (_{2}^{cnt_x} \right )\) 种,\(cnt_i\) 表示 \(i\) 的数量。区间内随便选一对的方案数是 \(\left (_{2}^{r-l+1} \right )\),答案就是这俩比一下就完了,之后莫队扩缩区间维护。

Submission

P5268 [SNOI2017] 一个简单的询问

\(get(l,r,x)\) 表示 \([l,r]\) 区间内 \(x\) 的出现次数,求 \(\sum get(l_1,r_1,i)\times get(l_2,r_2,i)\)

会发现这个式子很难直接推,考虑做一下差分,\(get(l_1,r_1,x)\) 可以拆成 \(get(1,r_1,x) - get(1,l_1-1,x)\)

拓展到整个式子(令 \(g(l,x)\) 表示 \(get(1,l,x)\))

\[get(l_1,r_1,i)\times get(l_2,r_2,i)=(g(r_1,i)-g(l_1-1,i))\times (g(r_2,i)-g(l_2-1,i)) \]

\[=g(r_1,i)g(r_2,i)-g(l_1-1,i)g(r_2,i)-g(r_1,i)g(l_2,-1)+g(l_1-1,i)g(l_2-1,i) \]

做个前缀和,就可以将整个式子当作四个询问,直接莫队统计答案即可。

Submission

P4396 [AHOI2013] 作业

这题相对于板子,只是加了个取值在 \([l,r]\) 的限制,对于这个东西,完全可以考虑树状数组,每次莫队扔进树状数组,出来直接前缀和统计答案即可。

复杂度 \(O(n\sqrt n\log n)\)

Submission

带修莫队

在区间问题中,可能会存在修改操作,虽然是离线算法,但莫队也是能做的。

假设普通莫队有 \((i,j)\) 两个维度,表示区间左右端点,那我们可以再加上一维时间维 \((i,j,t)\) 表示区间在第 \(t\) 秒的答案。

P1903 数颜色 / 维护队列

以本题为例,将时间维加入排序,当作排序的第三关键字。莫队操作中,假如当前有一个修改操作,将 \(a\) 位置与 \(b\) 位置交换,将 \(a\) 位置 \(del\),将 \(b\) 位置 \(add\)。即可,反操作只是将 \(a\)\(b\) 交换。

Submission

树上莫队

现在考虑将莫队放到树上,其实直接按照欧拉序把树扔到一维平面上,欧拉序这东西就是每次深搜走到走回来都记录一下,这东西剖一下就好了,但是 \(lca\) 可能不在一段欧拉序中,所以需要特判,之后做莫队即可。

Count on a tree II

模板题。

Submission

P4074 [WC2013] 糖果公园

给定树上 \(n\) 个数,每个数有 \(w_i\) 的权值,区间内第 \(i\) 个数的价值权重是 \(v_i\),总权值定义为区间内 \(\sum w_i\times v_{cnt_i}\),每次单点修改或者查询链上价值和。

由于是普通莫队,直接增加/减少上式即可,没什么好强调的,重点的是时间维度的意义,代表的是修改操作的下标,对应修改操作也是原树内固定的,不用再映射,注意欧拉序上的分类讨论,标记数组不要忘记。

Submission

回滚莫队

变种莫队,用于处理难以增加/删除的问题,比如区间众数,\(O(1)\) 增加,\(O(n)\) 删除,我们就可以只进行一类操作,通过回滚解决问题,这也将回滚莫队分为只增不删莫队和只删不增莫队,此处先介绍只增不删莫队。

回滚莫队的流程:

  • 序列分块,划分出每个询问左右端点的所在块,通过排序使得左端点按所在块排序,右端点根据左端点升序排列。

  • 分情况讨论,假如 \(l\)\(r\) 在同一块内,我们可以 \(O(\sqrt n)\) 的处理询问

  • \(l\)\(r\) 为莫队操作的区间,假如 \(l\)\(r\) 不在同一块内,\(L\)\(R\) 为左端点所在块的左右端点,\(x\)\(y\) 为询问的左右端点。初始时,令 \(l \gets R+1\)\(r \gets R\)

  • 介于这种情况下通常认为增加是 \(O(1)\) 的,我们先移动 \(r\)\(y\)记录下当前答案,然后新建变量,记录 \(l^{'}\) 向左增加的答案,之后统计答案,将 \(l\) 指针删掉来时增加的量,回到 \(R+1\),实现回滚。

  • 当然,这只是一个块内询问的处理方法,假如当前询问与上一次询问不在同一块内,需要重新移动 \(l\)\(r\)\(R+1\)\(R\),或许可以将这种回滚莫队看作对每个块都做一遍莫队( ? )。

AT_joisc2014_c 歴史の研究

价值定义为区间内某值出现次数与该值的乘积,每次询问求区间最大价值。

好像比板子还要板,拿这个当板子挺好。

Submission

P5906 【模板】回滚莫队&不删除莫队

定义价值为区间内相同值的下标差绝对值,求区间价值最大值。

记区间内每个值出现的最早/最晚出现的位置为 \(min_{a_i}\)\(max_{a_i}\),向右增加时,注意需要时刻更改 \(max_i\),在回滚时,假如当前 \(max_i = i\),说明已经找到了最靠右的位置,直接清零。

注意莫队的移动顺序和数组清理。

Submission

关于莫队的一些注意问题

奇偶优化回滚莫队是不能用的。

注意莫队移动指针时的顺序:

while(l>q[i].l) add(--l);
while(r<q[i].r) add(++r);
while(l<q[i].l) del(l++);
while(r>q[i].r) del(r--);
http://www.hskmm.com/?act=detail&tid=8626

相关文章:

  • 0voice-2.1.1-网络io与io多路复用select/poll/epoll
  • Java基本语句-分支语句
  • 丘成桐谈AI
  • 异常检测在网络安全中的应用 - 实践
  • 大文件分片上传
  • 人小鼠免疫细胞maker基因 - un
  • HyperWorks许可配置
  • 国标GB28181视频平台EasyGBS如何解决安防视频融合与级联管理的核心痛点?
  • python基础-推导式
  • 人 CD 抗原完全指南 - un
  • Java入门知识
  • AUTOSAR网络管理
  • 写用例注意点
  • 12 路低延迟推流!米尔 RK3576 赋能智能安防 360 环视
  • A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
  • Alternating Subsequence
  • 白鲸开源“创客北京2025”再摘殊荣,聚焦Agentic AI时代数据基础设施建设
  • python基础-公共操作
  • 天翼云第九代弹性云主机:让每一次计算快人一步
  • 若依(RuoYi)框架漏洞总结
  • 第一次个人项目作业_论文查重
  • 2025年版《中科院期刊分区表》与2023年版对比表,附名单可直接查阅
  • 对马岛之魂
  • 2019年双因素认证最佳实践指南
  • Account Kit(华为账号服务)再进化,开发者接入效率飙升!
  • Codeforces Round 1051 (Div. 2) D题启发(DP
  • Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
  • 关于proxmox 制作虚拟机模板的动态dhcp问题
  • Oracle清理:如何安全删除trace, alert和archivelog文件?
  • 软件工程个人项目