ST表
直接上代码板子(要最大值直接改成max就好)
int d[1000006][25];
int mn[1000006];
void rmq_init()
{
for(int i=1;i<=n;i++)
d[i][0]=a[i];//初始化
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
for(int len=1;len<=n;++len){
int k=0;
while((1<<(k+1))<=len)
k++;
mn[len]=k;
}
}
int rmq(int L,int R)
{
int k=mn[R-L+1];
return min(d[L][k],d[R-(1<<k)+1][k]);
}
d[i][j]的值表示为区间(i,i+2^j-1)的最值
d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);看起来很复杂 可以代入一个数据看看 让i=5,j=3
d[5][3]=min(d[5][2],d[9][2])
即min(5,12)=min((5,8),(9,12)); 这种推理便是动态规划的思想
如果假设我们要知道(5,10)区间的最值 首先我们求区间长度=6 , 而4是最大的小于6的2的幂次方 5+4-1=8 10-4+1=7
即min(5,10)=min((5,8),(7,10))
mn[]数组即为求最大的小于区间长度的2的幂次方 也可以用log2(r-l+1)来解决
(其实说那么多 记住代码模板就好哈哈哈哈哈)
例题洛谷P3865 //不用快读会TLE
#include <iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
int n,m;
int a[1000006];
int d[1000006][25];
int mn[1000006];
int L,R;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
void rmq_init()
{
for(int i=1;i<=n;i++)
d[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
for(int len=1;len<=n;++len){
int k=0;
while((1<<(k+1))<=len)
k++;
mn[len]=k;
}
}
int rmq(int L,int R)
{
int k=mn[R-L+1];
return max(d[L][k],d[R-(1<<k)+1][k]);
}
int main(){
cin >> n >> m;
for(int i=1;i<=n;i++){
a[i]=read();
}
rmq_init();
for(int i=1;i<=m;i++){
L=read();
R=read();
printf("%d\n",rmq(L,R));
}
return 0;
}
// freopen("testdata.in", "r", stdin);

浙公网安备 33010602011771号