[数据结构] ST表 | ST表的应用 | 解决RMQ问题

ST表

概览与说明

1、 设计目标

ST表(Sparse Table)用于高效解决静态区间最值查询(RMQ)问题,通过倍增思想实现 O ( n l o g n ) O(n log n) O(nlogn) 预处理 O ( 1 ) O(1) O(1)单次查询,适合处理不修改数据的场景。

2、 预处理与存储结构

  • 定义二维数组st[i][j],表示从位置 i i i 开始、长度为 2 j 2^j 2j 的区间的最值(如最大值)。
  • 递推关系 s t [ i ] [ j ] = m a x ( s t [ i ] [ j − 1 ] , s t [ i + 2 j − 1 ] [ j − 1 ] ) st[i][j] = max(st[i][j-1], st[i + 2^{j-1}][j-1]) st[i][j]=max(st[i][j1],st[i+2j1][j1]),即通过合并两个相邻子区间的最值得到更大区间的最值。

3、 对数表优化

预处理log_table[i]数组,快速计算区间长度对应的指数 k k k ( 满足 2 k ≤ l e n 2^k ≤ len 2klen ),避免重复调用 l o g log log 函数,提升查询效率。

ST表的实现代码

1、 预处理Log表

int log_table[MAXN];
void init_log() {
    log_table[1] = 0;
    for (int i = 2; i < MAXN; i++) 
        log_table[i] = log_table[i/2] + 1;
}

2、 构建ST表

int st[MAXN][21]; // 第二维大小设为log2(MAXN)+1
void build(int a[], int n) {
    for (int i = 1; i <= n; i++) st[i][0] = a[i]; // 初始化长度为1的区间
    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]);
}

3、 区间查询

int query(int l, int r) {
    int k = log_table[r - l + 1];
    return max(st[l][k], st[r - (1 << k) + 1][k]);
}

关键细节、优化及说明

细节处理:

  1. 边界处理
  • 构建时需保证 i + ( 1 < < j ) − 1 < = n i + (1 << j) - 1 <= n i+(1<<j)1<=n ,防止数组越界。
  • 查询时通过 r − ( 1 < < k ) + 1 r - (1 << k) + 1 r(1<<k)+1 确保分割后的区间覆盖原区间且不越界。
  1. 空间与时间权衡

    • 空间复杂度为 O ( n l o g n ) O(n log n) O(nlogn) ,适用于数据规模较大的场景。

    • 与线段树( O ( n ) O(n) O(n) 空间)相比,ST表查询更快但不支持动态修改。

典型应用场景:

  1. 静态区间最值(RMQ问题):

    如洛谷P3865,直接应用模板查询最大值。

  2. 扩展操作:

    • 区间最小值:将max替换为min
    • 区间GCD/按位与/或:利用可重复贡献性质,修改合并逻辑。
  3. 高维RMQ:
    二维ST表预处理子矩阵最值,查询时分解为四个子矩阵。

对比其他数据结构:

结构预处理时间查询时间动态更新适用场景
ST表 O ( n l o g n ) O(n log n) O(nlogn) O ( 1 ) O(1) O(1)不支持静态区间最值
线段树 O ( n ) O(n) O(n) O ( l o g n ) O(log n) O(logn)支持动态区间操作
单调队列 O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)支持滑动窗口最值

练习题目推荐:

  1. 模板题

  2. 变种应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值