st算法,将区间分成两个小区间,比较两个小区间的最值,注意dp数组范围千万不要取的过大了,超出1e8会导致程序崩溃!!!

alt

dp递推**,确定递推公式**s为起始区间,k为区间长度2^k中的k 不同的k,所在的dp二维数组中的最值不同,对于一个区间,化成两个区间比较即可,两个区间有交集,且最终可以合并成一个区间

#include <bits/stdc++.h>
using namespace std;
const int maxn=500001;
int n,m;//全局变量,便于函数使用
int a[maxn],dp_max[maxn][40];//求区间最大值,所以dp——max,2^40已经很大了
void st_init(){//解决函数,st算法
    for(int i=1;i<=n;i++)
    dp_max[i][0]=a[i];//初始化区间长度是为长度为一的值
    int p=log2(n);
    for(int k=1;k<=p;k++)
    for(int s=1;s+(1<<k)<=n+1;s++)
    dp_max[s][k]=max(dp_max[s][k-1],dp_max[s+(1<<(k-1))][k-1]);//K-1是因为是一个递推的过程,从前往后的,找到最值,注意括号。
}
int solve(int L,int R){//因为有多个答案,所以构造函数解决问题
  int k=log2(R-L+1);//先求出区间长度的k值(2^k)
  return max(dp_max[L][k],dp_max[R-(1<<k)+1][k]);//找到剩下的额外长度的区间与dp递推所得的2^k的区间进行一个比较,才能得到最终答案
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    cin>>a[i];
    st_init();
    for(int i=1;i<=m;i++)
    {
        int L,R;
        cin>>L>>R;
        cout<<solve(L,R)<<endl;
    }
    return 0;
}