尽人事,听天命。|

Jerrycyx

园龄:2年9个月粉丝:2关注:1

2025.2.27 闲话:普通莫队的正确与错误写法

远古错误排序

long long ago,我以为莫队就是把区间询问按照左端点为第一关键字、右端点为第二关键字排序,这样移动端点就可以做到 \(O(n\sqrt{n})\) 的时间复杂度了。事实上,如果出题人不刻意卡的话,复杂度也确实差不多是这样。然而,这个方法是可以卡的。

首先,左端点是单调的,移动次数为 \(O(n)\),这个没毛病。

但是,对于右端点,我们有方法让它多次大跳,即构造形如以下数据:

[1,n]
[2,3]
[3,n]
[4,5]
[5,n]
...

这样,每走一次右端点都要移动约 \(n-l\) 次,全部加起来用等差数列求和公式一算,好家伙卡成 \(O(n^2)\)

正确排序

将整个数列分为 \(\sqrt{n}\) 块,左端点在同一块内的按照右端点排序,不在的按照左端点(所在块编号)排序。这样,我们就将所有询问分为了 \(\sqrt{n}\) 组,每组内右端点单调,两个左端点距离不超过 \(\sqrt{n}\)

在这样的数列上移动,\(n\) 个左端点每个最多移动 \(\sqrt{n}\) 即可转移到下一个询问区间;\(\sqrt{n}\) 组每组内右端点一共最多移动 \(n\) 次;共 \(\sqrt{n}\) 次跨块移动,每次最多移动 \(n\) 次。总时间复杂度 \(O(n\sqrt{n})\)

最优块长

上面按照一般分块的想法把块长设定为 \(\sqrt{n}\),但这样某些时候是不优的。

假设数列长为 \(n\),询问数量为 \(m\)。设块长为 \(S\),那么整个数列将被分为 \(\frac{n}{S}\) 块。

  • 左端点:每个左端点最多移动 \(S\) 次,一共最多 \(mS\) 次;
  • 右端点:每块内最多移动 \(n\) 次,数列有 \(\frac{n}{S}\) 块,所以一共最多移动 \(\frac{n^2}{S}\) 次。
  • 跨块移动:共有 \(\frac{n}{S}\) 次这样的移动,每次最多移动 \(n\) 次,所以最多也是 \(\frac{n^2}{S}\) 次。

因此,时间复杂度为 \(O(\frac{n^2}{S}+mS)\),高一不等式知识可得 \(\frac{n^2}{S}+mS \ge 2\sqrt{\frac{n^2}{S} \times mS} = 2n\sqrt{m}\),即最优时间复杂度为 \(O(n\sqrt{m})\)。此时 \(\frac{n^2}{S}=mS\),解得 \(S=n\sqrt{m}\),这就是最优块长。

莫队移动顺序

记住一条就行了:先扩大区间再缩小区间。

这一条我似乎很早以前就发现了,但是现在才看到详细证明。

参考资料

posted @   Jerrycyx  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起