首页 > 其他 > 详细

【总结】st表

时间:2020-02-03 19:42:02      阅读:66      评论:0      收藏:0      [点我收藏+]

对于一类问题:

RMQ(Range Minimum/Maximum Query) 区间最值查询

给一个序列a[1],a[2],…,a[n],每次查询一个区间的最小值

我们可以用线段树解决,也可以一种更简单的数据结构st表来解决

st表相较于线段树而言时间复杂度更低,代码也更简洁

但是st表所能解决的问题非常有限

一句话总结就是:st表能解决的问题线段树一定能解决,但线段是能做到st表做不到

算法实现

运用倍增的思想,我们令\(f[i] [k]\)数组表示区间\([i,i + 2^k-1]\)中的最小值

\(f[i] [0]= a[i]\)

\(f[i] [k-1] = min(f[i] [k],f[i + (1<< k)] [k])\)

查询时给了一个区间[l, r],我们找一个最大的j满足\(2^j <= r - l + 1\)

于是我们可以用\(f[l] [j]\)\(f[r – 2^j + 1] [j]\)来覆盖这个区间,得到最小值

也即\(answer = min(f[l] [j], f[r – (1 << j) + 1] [j])\)

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,l,r;//这是个st表emm可我不会 
int Max[100001][22];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&Max[i][0]);//读入emm他到他本身的区间最大值就是他w
    } 
    for(int j=1;j<=21;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
        }
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&l,&r);
        int a=log2(r-l+1);
        printf("%d\n",max(Max[l][a],Max[r-(1<<a)+1][a]));
    }
    return 0;
}

【总结】st表

原文:https://www.cnblogs.com/huixinxinw/p/12256781.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!