ST表可以解决静态区间极值的问题。
倍增DP的思想。
f i j的i表示从i开始的2^j长度区间的极值。
如何转移呢?对于一段长度为4的区间可以拆成2个2的。一个8拆成4和4.
所以nlogn转移。
拆成前后两段小区间的极值。
查询的时候预处理下log值。
一段区间的极值等于前面左端开始log长度与从右端开始log长度。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n,m;
int a[MAXN],f[MAXN][25],lg[MAXN];
void get_log(int n){
int log=0;
for(int i=1;i<=n;i++){
lg[i]=(1<<log+1==i)?++log:log;
}
}
int query(int l,int r){
int k=lg[r-l+1];
return max(f[l][k],f[r-(1<<k)+1][k]);//因为那个数也算在区间里,所以+1.
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
f[i][0]=a[i];
}
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)-1<=n;j++){
f[j][i]=max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
}
}
get_log(n);
for(int i=1;i<=m;i++){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r));
}
return 0;
}