ST表详解+模板

ST表

基本概念

ST表是一个用来处理区间最值查询(RangeMaximum/Minimum Query)的离线算法。该算法分 为离线预处理O(n log n)和查询O(1)两个部分,其用到了倍增的思想。
某个区间查询问题是否适用ST表,关键在于其进行的操作是否允许区间重叠,例如max(a,b,c) = max{max(a,b),max(b,c)}就可以用ST表维护,而区间和问题则不能维护。

问题描述

给定一个长度为n的序列,有m次询问,每次给定区间[L , R],求区间内最大值。

算法思路

定义st表
我们设 st[i][j] 为从 i 开始的向后 2^j 个数中的最大值。假设这n个数存放的序列a中,根据定义 st[i][j] = max{a[k] | i <= k <= i+2^j - 1}。
查询操作
假设,我们要查询区间 [L,R] 中的最大值,由ST表定义,我们可知,我们可以查询从 x 开始,直至区间末尾的任意区间,由此特性,我们豁然开朗:以 区间[L,R] 为例,我们可以查询区间 [L,x] (x 是不超过 R 的最大数);同理,我们也可以查询区间 [x,R] (x 是不小于 L 的最小数);
由此得解
ans = max {st[L][k],st[R - (1<<k)+ 1][k]}
这里的k要取,使 L+2^k <= R 的最大值;
预处理
我们在上述证明了查询操作确实是O(1)的,所以如果我们真的能按照st表定义的那样去更新它,那 么该算法就真正的完成了。更新st表用到了动态规划的思想。
更新中仍然用到了倍增的思想,使得更新操作从O(n^2)优化到了O(n log n),初始状态st[x][0] = a[x],st[x][j] = max(st[x][j-1] , st[x + 1<<(j-1) ][j-1])。其思想和上述重叠查询类似,不再赘述。 但是要注意更新顺序,因为其中 j (第二维)才是阶段,而第一维 x 是状态,所以对于 j 的循环要 放在最外层。

模板

预处理
void init(){
    Log[1] = 0;//预处理log函数
    for(int i = 2;i <= n+1;i++) 
        Log[i] = Log[i/2]+1;
    for(int i = 1;i <= n;i++)
         st[i][0] = a[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]);
        }
    }
询问操作
int ask(int l,int r){
    int k = Log[r-l+1];
    int mx = max(st[l][k],st[r-(1<<k)+1][k]);
    return mx;//printf("%d %d\n",k,mx);
} 
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值