莫队算法的原理讲解,就不多做解释,网上一大片
学习资料推荐:
https://www.luogu.org/blog/codesonic/Mosalgorithm
莫涛大神的知乎
分块思想和时间复杂度
这篇文章的分块思想(如何让L和R这两个指针变得更少)和普通莫队的时间复杂度证明不是很好。
在上篇文章的时候我们提到用分块的思想来优化:对于两个询问,若在其l在同块,那么将其r作为排序关键字,若l不在同块,就将l作为关键字排序(这就是双关键字)
也就是说这个序列我们分成了块,每一块都x个询问,且这x个询问的右端点是递增的,然后我们先对这一块查找计算。
这样就可以优化时间复杂度么,我们看一下严格的证明(摘自大米饼的博客):
首先,枚举m个答案,就一个m了。设分块大小为unitl
下面给出证明:
我们分类讨论:
①l的移动:若下一个询问与当前询问的l所在的块不同,那么只需要经过最多2*unit步可以使得l成功到达目标.复杂度为:O(m*unit)
②r的移动:r只有在Be[l]相同时才会有序(其余时候还是疯狂地乱跳,你知道,一提到乱跳,那么每一次最坏就要跳n次!),Be[l]什么时候相同?在同一块里面l就Be[]相同。对于每一个块,排序执行了第二关键字:r。所以这里面的r是单调递增的,所以枚举完一个块,r最多移动n次。总共有n/unit个块:复杂度为:O(n*n/unit)
总结:O(n*unit+n*n/unit)(n,m同级,就统一使用n)
根据基本不等式得:当unit为sqrt(n)时,得到莫队算法的真正复杂度:
O(n*sqrt(n))
优化:
快读快写就不说了(很快的)
奇偶性排序
学习文章还提到了:奇偶性排序
这样能快是因为右指针移到右边后不用再跳回左边,而跳回左边后处理下一个块又要跳回右边,这样能减少一半操作,理论上能快一倍
代码:
//return pos[a.l]
b.r));///奇偶排序 分块的优化
sz=n/sqrt(m*2/3);
普通莫队模板
///莫队算法模板:求区间不同数的个数
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
带修改的莫队
///带莫队算法模板:求区间不同数的个数+单点修改
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
例题:
【BZOJ 2038 [2009国家集训队]小Z的袜子(hose)】 (莫队算法+数学公式)
Codeforces617 E . XOR and Favorite Number (莫队算法+异或)
1188 - Fast Queries (莫队算法)
NBUT 1457 Sona (莫队算法+离散化)
Codeforces - 220B Little Elephant and Array (莫队模板题+离散化)
codeforces 86D. Powerful array (莫队算法)
P1903 [国家集训队]数颜色 / 维护队列 (带修莫队算法模板:求区间不同数的个数+单点修改)
codeforces 940f Machine Learning 【 带修改莫队+离散化】