莫队学习笔记[未完待续]
000 引入
莫队,由前国家队队长莫涛发明,是一种区间维护区间状态的离线也可在线的算法。
其核心是对询问进行分块,并适当地调整询问顺序。
001 普通莫队
算法流程
我们把(sqrt{n})作为块大小进行分块并编号。
再把左端点所在块编号作为第一关键字,右端点作为第二关键字且升序排序。
然后按照顺序依次解决所有询问即可。
具体解决问题遵循以下步骤:
-
移动一步区间,计算答案增量,进行(O(nsqrt{q}))次,单次(O(a))
-
移动一步区间,重新维护数据结构,进行(O(nsqrt{q}))次,单次(O(b))
-
到达目标区间,计算答案,进行(O(q))次,单次复杂度(O(c))
算法复杂度
对于维护区间状态问题,如果我们已知区间([l, r])状态的情况下,我们能在(O(T))的时间内使得该区间的左或右端点移动一格并维护出相应的状态,那么莫队算法的复杂度即为(O(nsqrt{n}cdot T))
代码实现
while (l > q[i].l) add(a[--l]);
while (r < q[i].r) add(a[++r]);
while (l < q[i].l) del(a[l++]);
while (r > q[i].r) del(a[r--]);
当前处理的到底是(l)还是(r)并不重要,重要的是当前区间到底是扩大还是缩小。
注意扩大区间一般放在缩小区间的前面,这样是为了防止区间长度变成负数情况的出现。
题目练习
002 带修莫队
003 回滚莫队
004 树上莫队
005 二次离线莫队
006 卡常技巧
inline和register
多用吧,有递归的时候千万别用inline
调整块大小
在考场上,推出理论的最优块大小后,可以尝试在最优值的附近稍微调整块的大小。
奇偶数升降排序
一般我们排序是把左端点所在块编号作为第一关键字,右端点作为第二关键字且升序排序。
考虑优化,我们可以在左端点所在块编号是奇数时,右端点升序,当左端点所在快编号是偶数时,右端点降序。
这样能快是因为指针移到右边后不用再跳回左边,而跳回左边后处理下一个块又要跳回右边,这样能减少一半操作,理论上能快一倍