莫队学习笔记
莫队,一个很好玩的算法,基础莫队可以以 \(O(m\sqrt{n})\) 轻松处理 RMQ 一类的问题。狠狠恶心一下不爱开大数据的出题人
文章内普遍认为 \(n,m\) 同阶。
文章中的“一个块中的询问”指所有询问中 \(l\) 位于这个块的询问。
从基础开始。
普通莫队
对于 RMQ 问题,我们一般采取 ST 表、线段树等 log 级别的数据结构维护,但有些题目很难用这些数据结构维护,此时可以尝试莫队。
介绍
首先,莫队的底层逻辑是由 \([l,r]\) 区间的答案来更新 \([l-1,r]\),\([l+1,r]\),\([l,r-1]\),\([l,r+1]\) 的答案。大多数情况下,这个转移是 \(O(1)\) 的,不过有的题也会改。
莫队就是让一对 \([l,r]\) 不断的在 \([1,n]\) 上移动,以此记录每个查询的结果。
如果我们在线实现这一操作,容易发现可能被卡到 \(O(nm)\) 的复杂度,莫队就是要让查询离线,找一个顺序让区间移动的次数尽量少,做到 \(O(m \sqrt{n})\) 复杂度。
优化方法
容易发现,可以尽量让 \(l\) 不动,让 \(r\) 不断在区间上移动查询。于是我们就可以对查询以 \(l\) 为第一关键字排序,以 \(r\) 为第二关键字排序。
但是随便模拟一下就会发现这玩意也太好卡了吧,我只需要让每个 \(l\) 都不同,然后让 \(r\) 的差距特别大不就行了?
于是,就涉及到另一个毒瘤数据结构了————分块,没学过的朋友们可以去稍微看一下,基础不难。
对于这 \([1,n]\) 的序列,将它分成 \(\sqrt{n}\) 个块,所以每个块的长度也是 \(\sqrt{n}\) 级别的。
然后,我们以 \(l\) 所在的块为第一关键字,以 \(r\) 为第二关键字排序,容易发现,一个块中的所有查询,\(l\) 移动的量级为 \(\sqrt{n}\),\(r\) 最多移动 \(n\) 次。
实现
bool cmp(node x,node y){
if(pos[x.l]==pos[y.l]){
return x.r<y.r;
}
return x.l<y.l;
}
奇偶性优化
对于每个块,如果它的编号为奇数,那么让其中的查询以 \(r\) 升序排序,为偶数则以 \(r\) 降序排序。它可以让查询的 \(l\) 在不同块时,\(r\) 移动的长度尽量小。在查询比较密集时优化效果比较明显。
实现
bool cmp(node x,node y){
if(pos[x.l]==pos[y.l]){
if(pos[x.l]&1) return x.r<y.r;
return x.r>y.r;
}
return x.l<y.l;
}
带修莫队
普通莫队能干的事还是太少了,如果在查询里插点修改就完全不能用了。
所以,我们需要一个能修改的莫队。
时间戳
我不知道应不应该叫这个名字,但是你只要知道这玩意就是用来记录这是第几次出现的就行了。
很容易发现在处理当前区间查询时,将所有在这个查询前的修改改了就行,所以可以把查询和修改分开,拿一个指针记录修改改到哪了然后继续改。
实现
while(last<q[i].t){
last++;
if(t[last].p>=l && t[last].p<=r){
add(t[last].x);
del(a[t[last].p]);
}
swap(a[t[last].p],t[last].x);
}
while(last>q[i].t){
if(t[last].p>=l && t[last].p<=r){
add(t[last].x);
del(a[t[last].p]);
}
swap(a[t[last].p],t[last].x);
last--;
}
块长优化
明显地,因为多加了一个修改,如果还沿用原来的 \(\sqrt{n}\) 的块长,很容易被卡成 \(O(n^2)\)。
然后呢,怎么优化?我不会证明,有兴趣的自己搜一下。
对于结论来说,取 \(n^{\frac{2}{3}}\) 的长度为块长复杂度就能达到 \(O(n^{\frac{5}{3}})\) 的结果,已经是很优秀的复杂度了。
那你又说我怎么算出 \(n^{\frac{2}{3}}\) 啊,我又不会换底公式什么的。
那你就用 pow 呗,不会有人不知道这个函数能处理小数乘方吧。
回滚莫队
上强度的来了。
虽然但是带修莫队能做的题目还是太公式了,我们需要更加强力的算法!
于是,有人开始考虑解决这样的问题:如果莫队时增加和删除这两种操作只有一种比较好处理,我们怎么解决?
然后回滚莫队就诞生了,也被称为 不删除/不增加 莫队。
原理
容易得到回滚莫队不能使用奇偶性优化,因为奇偶性优化会使 \(r\) 必须增加和减少,也就必须要保证可以实现增加和删除两种操作。
对于每一个块内的询问,

浙公网安备 33010602011771号