前言:
在计算机科学领域,高效处理区间查询问题一直是算法设计的核心挑战之一。无论是在数据预处理、数据分析还是在线服务中,快速回答 “某个区间内的最大值 / 最小值是多少”“区间和是多少” 等问题,都对系统性能至关重要。稀疏表(Sparse Table,ST 表)作为一种经典的数据结构,凭借其O (n log n) 的预处理时间复杂度和O (1) 的单次查询时间复杂度,成为解决这类问题的理想选择。
解决什么问题
稀疏表常用于以下几种场景:
1.区间最小值/最大值查询(本文主要讲解这类问题)
2.均值和其他聚合统计的快速查询
3.处理静态数据集而需要频繁进行的查询操作
例题
思路
什么是ST表?
倍增的概念
“倍增”,简单来说就是成倍地增长。在算法设计中,它通过预先计算出一些具有特定长度(通常是 2 的幂次)的状态,然后利用这些状态快速组合出其他状态,从而在时间和空间上达到高效的处理效果。其核心在于利用 2 的幂次具有的可加性和二进制表示的特性,将原本需要逐步递推或遍历的过程进行优化。具体详情←
如何工作的?
模板
// 一句话题意:给定有 n 个数的序列,
// 和 m 次询问,求出每一次询问的区间内数字的最大值。
#include <iostream>
#include <cmath>
using namespace std;
#define MAXN 100002 // 最多1e5个元素
#define LOGN 17 // ceil(log2(MAXN))
int n, arr[MAXN]; // 存n个数的序列,下标从1开始
int st[MAXN][LOGN]; // st[i][j] 表示,从i开始的2^j个数和中最大的一个
// 构建st表,注意+优先于<<
void build_sparse_table() {
for (int i = 1; i <= n; i++)
st[i][0] = arr[i];
for (int j = 1; (1<<j) <= n; j++)
for (int i = 1; i+(1<<j)-1 <= n; i++)
st[i][j] = max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
// 查询区间[l,r]的最大值
int query(int l, int r) {
int j = (int)log2(r-l+1);
return max(st[l][j],st[r-(1<<j)+1][j]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> arr[i];
build_sparse_table();
while (m--) {
int l, r; cin >> l >> r;
cout << query(l,r) << '\n';
}
return 0;
}
稀疏表是一种高效的查询结构,利用预处理来加速对静态数据的区间查询。在 C++ 中实现稀疏表不仅可以提升算法性能,同时也给我们提供了一个灵活的模板结构,方便用户根据需求选取不同的列操作意图(如最小值、最大值等)。虽然它的构建过程相对复杂,但一次预处理后可以提供极为高效的查询结果,极大满足了算法在大量数据处理中的需求。