莫队算法是一个很妙的算法,它可以通过对查询离线分块来降低算法复杂度。
但是仔细分析你会发现,莫队所有的复杂度都是修改左右端点造成的,而查询是 \(O(1)\) 的。
也就是说我们可以在莫队中套一个修改 \(O(1)\),查询 \(O(1\sim \sqrt{n})\) 的数据结构,这样总复杂度依旧是 \(O(n \sqrt{n})\) 的,但是它却可以做更多的事情。
例:有一个长度为 \(n\) 的数组 \(\{a_1,a_2...a_n\}\)。\(m\) 次询问,每次询问一个区间内最小没有出现过的自然数。
这个题目是洛谷的 P4137。
这个题的经典做法是主席树或者回滚莫队,我们现在考虑另一种做法。
先直接上莫队,这样我们是不好维护删除数的操作的。
考虑在莫队里面套上一个值域分块,修改的时候 \(O(1)\) 修改,查询的时候 \(O(\sqrt{n})\) 一个块一个块的跳。
虽然套了一个分块,但是复杂度是加在查询上面的 ,总复杂度仍然是 \(O(n\sqrt{n})\) 的。