ST 表模板。求静态区间最大值。
用 lg[n]
表示
⌊
log
2
n
⌋
\lfloor\log_2n\rfloor
⌊log2n⌋,预处理出该数组,然后用 st[i][j]
表示区间
[
i
,
i
+
2
j
)
[i,i+2^j)
[i,i+2j) 的最大值,则存在递推关系:
s t [ i ] [ j ] = max ( s t [ i ] [ j − 1 ] , s t [ i + 2 j − 1 ] [ j − 1 ] ) st[i][j]=\max(st[i][j-1],st[i+2^{j-1}][j-1]) st[i][j]=max(st[i][j−1],st[i+2j−1][j−1])
预处理的时间复杂度: O ( n log n ) O(n\log{n}) O(nlogn),查询一次的时间复杂度: O ( 1 ) O(1) O(1),总时间复杂度: O ( n log n + q ) O(n\log{n}+q) O(nlogn+q),其中 q q q 为查询次数。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,m,lg[MAXN],st[MAXN][20],l,r;
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
lg[0]=-1;
for(int i=1;i<=n;i++){
scanf("%d",&st[i][0]);
lg[i]=((i&(i-1))==0)?lg[i-1]+1:lg[i-1];
}
for(int j=1;j<=lg[n];j++)
for(int i=1;i+(1<<j)-1<=n;i++)
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
while(m--){
scanf("%d%d",&l,&r);
int k=lg[r-l+1];
printf("%d\n",max(st[l][k],st[r-(1<<k)+1][k]));
}
return 0;
}