莫队算法

来源:互联网 发布:智慧足迹数据 编辑:程序博客网 时间:2024/05/16 19:13

这名字···

这个算法是由之前的国家队队长莫涛巨神(Orz….%%%64)发明的,所以尊称莫队算法。

莫队算法

事实上,莫队算法这种东西,应该叫做——

一个优雅的暴力(引自Alan_Cty)

传说中能解决一切区间问题的算法

如果我们知道区间[L,R],就能在O(1)求出[L1,R],[L+1,R],[L,R1],[L,R+1]的话,那就可以用莫队算法了。

有一种经典的问题:给你一些不带修改的区间询问,要求快速回答

显然,有一些我们可以通过线段树来完成,因为线段树是O(NlogN)

但是,线段树有的东西是维护不了的。

看一个例子

给你一个数列,若干询问,要求回答区间内同种颜色大小。

线段树很难做,怎么办?

用莫队算法!

莫队算法的实质是通过将询问排序,每个询问均由前一个询问(排序后的)转移得来,通过一定的排序优化时间复杂度。往往可以有O(NN)的效果

回到题目
显然对于两次询问L,RL,R,知道了L,R的答案,就可以暴力计算|LL|+|RR|次得出L,R的答案。

|LL|+|RR|。这个东西,数学上称之为曼哈顿距离

把每个询问看作是二维平面上的点,那么我们的最小总时间,就是这些点的最小曼哈顿距离生成树, 按照这个树的顺序做,复杂度变成了O(NN)(为什么?不好意思,我不会证),而且这个生成树连边也有特别的技巧,可以去看莫队在知乎上推荐的那篇。

然而这样有一点猥琐

有一个优美方便简洁好理解的替代品

分块大法好!

把整个序列分块,把L按照所在块的顺序为第一关键字,把RR本身!)为第二关键字排序。

为什么要分块不能直接排呢?

分块很好的减少了一种情况的影响。

L<L<L,并且距离很近,但是R<R<R,并且R与另外两个离得很远。如果直接按L排序就会浪费非常多的时间。

由于每个块的大小是N

分块使得两个询问之间差异平均到了L,R上。

因此,理论复杂度大约是O(NN),实际上是O(玄学??跑的过就行)

带上了修改,怎么办?

然后我们继续分块。

把二元组L,R变成三元组L,R,xx是这次询问在修改第几次后。

然后把R所在块看作第二关键字,x看作第三关键字排序即可。

转移时直接恢复(或删除)两次询问之间的修改。如果在区间内还要计算对答案的影响

然而修改的复杂度十分神奇,是O(N53),且最优分块方式是每块N23

复杂度的证明可以看看a_crazy_czy的博客

有一道板题
http://blog.csdn.net/hzj1054689699/article/details/51880644