莫队算法

概述

莫队算法是一种离线分块算法,用于解决序列上的区间查询问题。若区间 的答案能 扩展到相邻区间 ,则可在 复杂度内求出所有询问。

排序与分块

所在块编号为第一关键字, 为第二关键字排序。块大小取 时最优,总复杂度

奇偶排序优化:奇数块 升序,偶数块 降序,减少 指针回跳,可提速约 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--),否则会导致 使维护出错。

应用与例题

题目链接难度
P1972HH 的项链省选/NOI-
P2709小 B 的询问普及/提高-
P1494小 Z 的袜子省选/NOI-

扩展阅读

更多练习题见 路径D-DSA算法刷题

多平台练习

| 洛谷 | 本题单 | 竞赛基础 |
| POJ (北大) | PKU JudgeOnline | 经典题目,适合巩固 |
| HDU (杭电) | HDU OJ | 暑期多校训练 |
| Codeforces | Codeforces | 国际竞赛,适合提升 |