ST表主要用于解决RMQ问题(区间最值问题)
当然你可以用线段树等,但今天用一种ST表(倍增算法)

ST表是倍增算法的一个典型应用
暴力做RMQ问题,往往会超时,ST表利用对其进行优化

给定一段序列A,ST算法能在O(NlogN)的时间预处理后,以O(1) 的复杂度查询,在线回答在一段区间l,r 中最大(小)值是多少。

f[i][j]用于表示在序列a中, 从第i位数字往后数2^j^个数,这个区间内的最大值,即区间[ i , i + 2 ^j^ ]内取得的最大值。

而这段区域的最大值等于左右子区间的最大值,2^j^ = 2 * 2 ^j-1^ = 2^j-1^ + 2^j-1^,把区间[i,i+2^j^]分成[i , i + 2^j-1^ ] [ i + 2^j-1^ + 1,2^j^]
(即f [ i ] [ j - 1 ] 与 f [ i + 2 ^j-1^ - 1 ] [ j -1 ] )

我们可得:F [ i ] [ j ] = max ( F [ i ] [ j - 1 ] , F [ i + 2 ^j-1^ - 1 ] [ j - 1 ] )
递推边界为f[i][0]=a[i]

其实说白了就是:相求大区间就先求出小区间,求小区间就求小小区间,一直这样套娃到最低层。

但是我们查询的区间不一定总是2的倍数,也有可能会超出区间
所以我们询问区间[l,r]时要用一个k,k=log2(len),len为区间的长度,k向下取整
len=r-l+1
2^t^<len<2^t+1^
左右区间最大值分别是F [ l , k ] 与F [ r - 2^k^ + 1 , k ]

#include<cstdio>
#include<iostream>
#include<cmath>

using namespace std;

long f[100001][40];
int n,m;

void ST()//预处理
{
    for(int k=1;k<=(int)log2(n);k++){
        for(int i=1;i<=n-(1<<k)+1;i++){
            f[i][k]=max(f[i][k-1],f[i+(1<<(k-1))][k-1]);
        }
    }
}
int query(int l,int r)//查询
{
        int k=log2(r-l+1);
        return max(f[l][k],f[r-(1<<k)+1][k]);

}
int a[100];
int main(){
    cin>>n>>m;

    int temp;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);

        f[i][0]=a[i];
    }

    int l,r;
    for(int i=1;i<=m;i++){
    scanf("%d%d",&l,&r);
    cout<<query(l,r);
    }

    return 0;
}