莫队算法

  莫队算法是由之前的国家队队长莫涛发明,故称为莫队算法。其用于处于静态区间查询。

区间莫队

  对于区间查询,我们一般会使用主席树或树套树之类吊炸天的数据结构来进行处理。这是基于我们可以对区间进行二分,并通过分治的方式保证拥有对数级别的性能。当然前提是查询的内容要适合进行分治处理,对于形如最大值最小值,分治非常适合,但是也有非常不适合的,譬如我们要查询区间中重复次数最多的数值,这时候分治就失去了意义。这时候莫队算法就站了出来。

  对于上面的问题,如果在已知[l,r]上每个数字的重复次数,那么对于[l,r+1],[l,r-1],[l+1,r],[l-1,r]上的询问,可以在O(1)的时间复杂度内解决。直接按序执行查询,其时间复杂度将可能达到O(mn),其中n为区间长度,m为查询数目。莫队算法则需要对查询进行重新组织。定义两个查询[a,b]与[x,y]的距离为|a-x|+|b-y|,即二者的曼哈顿距离。如果我们将每个查询视作一个顶点,而两个查询之间的距离视作两个结点间的边长,将查询[0,0]视作起点,那么要发挥莫队算法的完全性能,我们需要找到从起点出发的一条经过所有顶点的最短路径。但是要找这样的一条路径显然是费事费力的,因此我们会选择另外一种方法-分块,降低莫队算法的时间复杂度。分块是这样的,我们将[1,n]均分为n/k个长度为k的块。之后我们对查询进行排序,排序的第一关键字是查询左边界所处的块的编号,而第二关键字是查询右边界。之后我们按排序好的结果逐一执行查询请求。

  时间复杂度的证明如下:

  对于每一个块,由于左边界落于该块中的查询的右边界递增,故右边界最多移动n次。由于总共有n/k个块,故最多移动n^2/k次。

  对于每一个块,由于左边界落于该块中的查询切换时,左边界最多移动k次,而总共切换最多发生m次,因此左边界最多移动km次。

  在一个块处理完进入另外一个块的时候,我们可能需要完全重置当前维护的区间的信息,即左右边界最多加总移动2n次,由于最多发生n/k次,故最多移动2n^2/k次。

  综合上面可知总的时间复杂度为O(nlog2(n))+O(km)+O(n^2/k)=O(nlog2(n)+km+n^2/k)。当m很小的时候,我们完全可以选择k为n,这时候时间复杂度为O(nlog2(n)),而当m较大时,我们可以选择k为1,此时时间复杂度为O(n^2+m)。下面是理论上应该选取的最优k值,仅用到简单的微分技巧:

$$ f\left(k\right)=n\log_2n+km+n^2/k $$ $$ f'\left(k\right)=m-n^2/k^2 $$ $$ f'\left(k\right)=0\Rightarrow mk^2=n^2\Rightarrow k=n/\sqrt{m} $$

此时的时间复杂度为$ O\left(n\cdot\left(\log_2n+\sqrt{m}\right)\right) $。

带修改莫队

  我们完全可以令莫队算法支持修改。假设区间长度为N,查询次数为Q,修改次数为M。查询和修改的次序任意。利用与一般莫队相同的方案。我们将区间按长度a进行切分,而将区间按长度b进行切分。对于每个查询,称其之前发生的修改次数为该查询的版本,记作(l,r,v),其中v为版本号。我们对查询进行分块,一个块中的所有查询(l,r,v),其l/a向下取整均相同,且v/b向下取整也相同。首先我们将所有查询(l,r,v)进行排序,排序的第一关键字是l/a向下取整,第二关键字是v/b向下取整,而第三关键字为r。之后依序执行查询。

  时间复杂度的证明如下:

  对于每一个块,右边界最多移动N次,而块数为N*M/(a*b),故执行次数为M*N^2/(a*b)。

  对于每一个块中的查询,左边界和版本号最多分别改变a次和b次,即块中查询执行次数为Q*(a+b)。

  对于块之间的切换,每次左边界和版本号最多修改2*a次和2*b次,即块间切换执行次数为Q*(a+b)。

  综合以上可见时间复杂度为O(M*N^2/(a*b)+Q*(a+b))。利用微分技巧可知:

$$
\frac{df}{da}=-\frac{MN^2}{\left( ab \right) ^2}\cdot b+Q=0\Rightarrow a^2b=\frac{MN^2}{Q}
$$

考虑到式子对于a和b是对称的,因此可以推出当下式成立时

$$
\frac{df}{da}=\frac{df}{db}=0
$$

必定有a=b。故可以得出

$$
a=b=\sqrt[3]{\frac{N^2M}{Q}}
$$

此时代入原来时间复杂度式子中可以得出最优的时间复杂度为$O\left( N^{\frac{2}{3}}M^{\frac{1}{3}}Q^{\frac{2}{3}} \right)$,由于一般Q=M,此时时间复杂度为$O\left( N^{\frac{2}{3}}M \right) $。

posted @ 2018-01-17 22:31  cccwiseee  阅读(613)  评论(0编辑  收藏  举报