莫队学习笔记
概述
莫队算法是由莫涛提出的算法,可以离线地解决一类区间查询问题,适用性极为广泛。
普通莫队
问题引入
给定一个具有n个元素的序列a,元素下标由1到n。给定m次询问,每次询问给出一个区间 [ l , r ] [l,r] [l,r], 并要求输出该区间的对应答案。
如果该问题满足以下性质:
- 如果已知 [ l , r ] [l,r] [l,r]的答案, 就可以在 O ( 1 ) O(1) O(1)的时间复杂度中得出 [ l − 1 , r ] , [ l + 1 , r ] , [ l , r − 1 ] , [ l , r + 1 ] [l-1,r],[l+1,r],[l,r-1],[l,r+1] [l−1,r],[l+1,r],[l,r−1],[l,r+1]的答案。
- 允许先得知所有m个查询的区间,再给出答案。(即,允许离线所有查询区间)
- m小于n, 或者m与n同阶。
那么就可以在 O ( n n ) O(n\sqrt n) O(nn)求出所有m个询问。
算法实现
step 1:分块。将位置 [ 1 , n ] [1,n] [1,n]分成 n \sqrt n n块, 每块的大小为 n \sqrt n n。这里无所谓向上取整还是向下取整, 向下取整不过就是多分一块而已。
step 2:利用性质2,将所有m个查询离线下来,对其进行排序。排序的方式是: 以查询区间的左端点 l l l所在的块为第一关键字, 以右端点 r r r本身的大小为第二关键字,非降序排序。此时便将查询区间分为 n \sqrt n n组, 其中所有左端点在同一个块内的查询区间为第 i i i组,.同时在同一组组内, 右端点的值非降序排列.
step 3:按照第二步排好的顺序,用性质1进行暴力转移,获取全部m次查询答案。
算法复杂度分析
因为问题的性质3,m与n同阶,所以下面复杂度分析中所有的m将可以用n代替。
step 1
显然时间复杂度是 O ( n ) O(n) O(n)
step 2
因为用到了排序,因此时间复杂度 O ( n log n ) O(n\log n) O(nlogn)
step 3
考虑这一步的时间复杂度由四部分组成:
-
区间的左端点在不同组间进行转移.
注意到此时的左端点是从一个块移动到下一个块, 其中距离最多为 2 n 2\sqrt n 2n, 根据问题的性质1, 每次左端点增减1的复杂度是 O ( 1 ) O(1) O(1)