RMQ/稀疏表加速静态区间查询

📅 2026/7/9 1:14:24 👁️ 阅读次数 📝 编程学习
RMQ/稀疏表加速静态区间查询

引言

  • 静态区间查询问题的定义与应用场景(如数组区间最小值、最大值等)。
  • 传统暴力查询的局限性(时间复杂度高)。
  • 引入稀疏表(Sparse Table)作为高效静态RMQ的解决方案。

稀疏表的基本原理

  • 稀疏表的核心思想:预处理与倍增思想。
  • 动态规划预处理数组:定义st[i][j]表示从索引i开始、长度为2^j的区间极值。
  • 状态转移方程:
    [ st[i][j] = \min(st[i][j-1], st[i + 2^{j-1}][j-1]) ]
  • 查询时通过二进制拆分覆盖区间,实现 (O(1)) 查询。

稀疏表的实现步骤

  1. 预处理阶段
    • 初始化st[i][0]为原数组值。
    • 按长度从小到大递推计算st[i][j]
  2. 查询阶段
    • 计算区间长度对应的最大幂次k(满足 (2^k \leq \text{区间长度}))。
    • 通过比较两个重叠区间的最小值得到结果:
      [ \min(st[l][k], st[r - 2^k + 1][k]) ]

代码实现(以C++为例)

int st[MAXN][LOG_MAXN]; // 稀疏表数组 int log2[MAXN]; // 预计算对数表 void preprocess(int n, int arr[]) { for (int i = 0; i < n; i++) st[i][0] = arr[i]; for (int j = 1; (1 << j) <= n; j++) { for (int i = 0; i + (1 << j) <= n; i++) { st[i][j] = min(st[i][j-1], st[i + (1 << (j-1))][j-1]); } } // 预计算log2表(可选优化) log2[1] = 0; for (int i = 2; i <= n; i++) log2[i] = log2[i/2] + 1; } int query(int l, int r) { int k = log2[r - l + 1]; return min(st[l][k], st[r - (1 << k) + 1][k]); }

性能分析与实测对比

  • 时间复杂度:预处理 (O(n \log n)),查询 (O(1))。
  • 空间复杂度:(O(n \log n))。
  • 对比其他数据结构
    • 与线段树对比:稀疏表查询更快但不支持动态更新。
    • 与树状数组对比:稀疏表更适合纯静态场景。
  • 实测数据:展示不同规模数据下稀疏表与暴力查询、线段树的性能差异(如1e6次查询耗时)。

优化与扩展

  • 对数表的预计算优化查询常数。
  • 扩展到多维稀疏表或支持其他可重复贡献操作(如GCD、按位与等)。
  • 结合分块或ST表解决动态RMQ问题。

总结

  • 稀疏表的适用场景与局限性。
  • 强调其在算法竞赛或高并发静态查询中的优势。

附录

  • 相关题目链接(如LeetCode、Codeforces例题)。
  • 完整代码与测试数据仓库地址(可选)。