ST表

st表

ST表是什么:

  ST表类似树状数组,线段树这两种算法,是一种用于解决RMQ(Range Minimum/Maximum Query,即区间最值查询)问题的离线算法与线段树相比,预处理复杂度同为O(nlogn),查询时间上,ST表为O(1),线段树为O(nlogn),st表的主体是一个二维数组st[i][j],表示需要查询的数组的从下标i到下标i+2^j - 1的最值。

ST表涉及思想:

  倍增,递推。

ST表怎么实现:

  用倍增的方法与递推式,预处理出第i个数分别到第i+2^j-1个数的极值,用一二维数组ex[i][j]表示。递推式为ex[i][j]=max(ex[i][j-1],ex[i+(1<<j-1)][j-1]),为之后查询时提供需要的数据。在查询时,查询区间为l—r,一般思路是:r=l+2^z-1,则ans=ex[l][l+2^z]。但往往事与愿违,r大部分情况还是l+2^z-1以外的东西。不过数据处理一下即可。

ST表查询的数据处理:

  在查询l—r的过程中,我们可用两段小的区间进行合并,用什么呢?[l—l+2^k]与[r-2^k+1—r],明显这两段的最小值是预处理过的,且两区间加起来正好是询问区间。所以ans=max(ex[l][k],ex[r-(1<<k)+1][k]),其中int k=log2(r-l+1),这样k自动向下取整,保证区间不会越界且正好合适。

最后是代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#define re register
using namespace std;
static const int N=1e6+5;
int ex[N][22];
int n,m,a;
inline int query(int l,int r){
    int k=log2(r-l+1);
    return max(ex[l][k],ex[r-(1<<k)+1][k]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(re int i=1;i<=n;i++){
        scanf("%d",&a);
        ex[i][0]=a;
    }
    for(re int j=1;j<=20;j++){
        for(re int i=1;i<=n-((1<<j)-1);i++){
            ex[i][j]=max(ex[i][j-1],ex[i+(1<<j-1)][j-1]);
        }
    }
    for(re int i=1;i<=m;i++){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",query(l,r));
    }
    return 0;
}
View Code

 

posted @ 2019-08-18 22:01  强乐还无味  阅读(229)  评论(0)    收藏  举报