RMQ问题
:查询区间最大值或者最小值
这里用ST表处理
ST表(动态规划的思想)
设f [i][st], i为元素起始下标,st为从i开始,长度为2^st 的最大值
1.预处理
f[i][0] 为从i 开始,长度为2^0 范围的最大值
for(int i=1;i<=n;i++){
f[i][0]=a[i];
}
2. f[i][0] [i,i]
f[i][1] [i,i+1] = max( f[i][0], f[i+2^0][0] )
f[i][2] [i,i+3] = max( f[i][1],f[i+2^1][1] )
f[i][3] [i,i+7] = max( [i,i+3], [i+4,i+7] ) = max( f[i][2],f[i+2^2][2] )
可以看出,对于区间为[i,st] 的区间,可以拆为 f[i][st-1] 和 f[i+2^(st-1)][st-1])
其实就是将区间对半,然后将两个半区间再比较最大值
循环下界问题
1. 这里的 j 的上限为 2^j<=n, (1<<j 表示2^j)
关于1<<j 的解释
1 左移 j 位
这是移位运算,左移
1<<1 表示把 二进制 数 0001 左移 1 位,变成 0010, 等于 2
1<<4 表示把 二进制 数 0001 左移 4 位,变成 0001 0000, 等于 16
2. i 的坐标也不能越界,i+2^j <= n+1具体解释看大佬博客
for(j=1;(1<<j)<=n;++j)
for(i=1;i+(1<<(j-1))<=n;++i)
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
至于查询,设k=log(r- l +1),则 因为k为下取整结果,最后可能长度不能覆盖(r-l+1),例如区间为[1,12]
而k最大=3 ,长度为8,到不了12,
所以用max( f[l][k] ,f[r-(1<<k)+1][k] ) ,即max( [1,8] , [5,12] )
以m为底的log函数表达式为 log(n)/log(2)或者直接写成 log2(n)
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int f[maxn][25];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
f[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i<=(n-(1<<j)+1);i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
int l,r,k;
for(int i=1;i<=m;i++){
scanf("%d %d",&l,&r);
k=log(r-l+1)/log(2);
int b=max(f[l][k],f[r-(1<<k)+1][k]);
printf("%d\n",b);
}
return 0;
}
来源:CSDN
作者:年离惊玉
链接:https://blog.csdn.net/qq_43842119/article/details/101680617