莫队算法

莫队算法

普通莫队

形式:给定一个长度为 \(n\) 的序列,有 \(q\) 次询问,每次询问给出 \(l,r\),问区间 \([l,r]\) 的答案。

要求:询问必须离线,且从区间 \([l,r]\) 转移到区间 \([l+1,r],[l-1,r],[l,r+1],[l,r-1]\) 的时间复杂度是 \(O(1)\) 的。

做法:关于 \(l\) 对询问分块,块长为 \(T\),每个块内对 \(r\) 从小到大排序。按照一个个块的顺序处理询问,移动左右端点从一个询问转移到另一个询问,移动时维护区间答案。

时间复杂度:块内左端点每次跳 \(O(T)\),一共有 \(q\) 个左端点,一个块右端点会移动 \(O(n)\),一共有 \(\frac{n}{T}\) 个块,不同块间转移是 \(O(n)\) 的,一共有 \(\frac{n}{T}\) 个块。总时间复杂度是 \(O(\frac{n^2}{T}+qT)\),根据基本不等式,时间复杂度 \(\le \sqrt{n^2q}=n\sqrt{q}\),块长 \(T\)\(\frac{n}{\sqrt{q}}\)。时间复杂度 \(O(n\sqrt{q})\)

例题:P1494 [国家集训队] 小 Z 的袜子

奇偶优化:奇数块 \(r\) 从小到大排序,偶数块 \(r\) 从大到小排序。

带修改莫队

问题:给定一个长度为 \(n\) 的序列,有 \(q\) 次询问,每次询问有两种:

  1. 给出 \(l,r\),问区间 \([l,r]\) 的答案。
  2. \(a_i\) 改成 \(x\)

用数据结构预处理序列上每个点每个时间是什么。显然用 mutiset 是好做的。

把每次询问答案看作三维数对 \((l,r,t)\)。离线做莫队。

\(l\) 分块,块长为 \(T\),每个块内对 \(r\) 分块,块长为 \(T\),按 \(T\) 从小到大排序。每个小块 \(t\) 最多移动 \(q\) 次,一共 \(\frac{n^2}{T^2}\) 个小块。每个小块内一次转移 \(l,r\) 最多移动 \(T\) 次,一共 \(q\) 次转移。不同小块间转移一次 \(r\) 移动 \(T\) 次,一共 \(\frac{n^2}{T^2}\) 个小块。不同大块间转移一次 \(l\) 移动 \(T\) 次,一共 \(\frac{n}{T}\) 个大块。总时间复杂度是 \(O(\frac{n^2q}{T^2}+qT+\frac{n^2}{T}+n)=O(\frac{n^2q}{T^2}+qT+n)\)

一般来讲,\(T\)\(n^{\frac{2}{3}}\) 时复杂度最优。总复杂度为 \(O(qn^{\frac{2}{3}})\)

回滚莫队

问题:给定一个长度为 \(n\) 的序列,有 \(q\) 次询问,每次询问给出 \(l,r\),问区间 \([l,r]\) 的最大/最小/mex 值。

例如求区间 mex 值,我们发现区间减少一个数答案是好维护的,但是增加一个数答案不好维护。

于是还是按照 \(l\) 分块,块长为 \(T\),每块的询问左端点满足在区间 \([l_{min},l_{max}]\)

我们在每个块中按 \(r\) 从大到小排序,预处理所有区间 \([l_{min},n]\) 的答案,对于每个询问,我们只需要从 \(n\) 开始不断向左移动右端点,移完存档一下目前的答案,然后向右移动左端点,求出询问的答案。之后回到存档,算下一个答案即可。

时间复杂度分析和普通莫队一样。

经验

【五一省选集训day4】Mansion 回滚莫队 + 分块

posted @ 2024-09-10 14:20  liyixin  阅读(8)  评论(0编辑  收藏  举报