莫队算法
概述
莫队算法是一种离线分块算法,用于解决序列上的区间查询问题。若区间 的答案能 扩展到相邻区间 ,则可在 复杂度内求出所有询问。
排序与分块
以 所在块编号为第一关键字, 为第二关键字排序。块大小取 时最优,总复杂度 。
奇偶排序优化:奇数块 升序,偶数块 降序,减少 指针回跳,可提速约 30%。
int unit;
struct Node {
int l, r, id;
bool operator<(const Node &x) const {
if (l / unit != x.l / unit) return l < x.l;
return (l / unit) & 1 ? r < x.r : r > x.r;
}
};模版框架
void move(int pos, int sign) { /* update nowAns */ }
void solve() {
int block = ceil(pow(n, 0.5));
sort(q, q + m);
int l = 1, r = 0;
for (int i = 0; i < m; ++i) {
while (l > q[i].l) move(--l, 1);
while (r < q[i].r) move(++r, 1);
while (l < q[i].l) move(l++, -1);
while (r > q[i].r) move(r--, -1);
ans[q[i].id] = nowAns;
}
}四个 while 顺序:必须先扩大区间(--l / ++r),再缩小区间(l++ / r--),否则会导致 使维护出错。
应用与例题
扩展阅读
- 带修莫队(modifiable-mo-algo)
- 树上莫队(mo-algo-on-tree)
- 回滚莫队(rollback-mo-algo)
更多练习题见 路径D-DSA算法刷题。
多平台练习
| 洛谷 | 本题单 | 竞赛基础 |
| POJ (北大) | PKU JudgeOnline | 经典题目,适合巩固 |
| HDU (杭电) | HDU OJ | 暑期多校训练 |
| Codeforces | Codeforces | 国际竞赛,适合提升 |