题意
给出一个序列,求某一个区间的最大值。(RMQ)
思路
ST算法,设 f[i][j] f [ i ] [ j ] 表示从序列的第 i i 个位置开始个数的最大值,我们可以得到公式 f[i][j]=max(f[i][j−1],f[i+2j−1][j−1]) f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i + 2 j − 1 ] [ j − 1 ] ) ,相当于把一个从 i i 到的区间分成了两个长度为 2j−1 2 j − 1 的区间。当我们查询最大值的时候,我们可以算出一个 k k ,就是让这个区间长度时, k k 的最大值,那么我们查询的区间的答案就为 max(f[l][k],f[r−2k+1][k]) m a x ( f [ l ] [ k ] , f [ r − 2 k + 1 ] [ k ] ) ,这两段刚好覆盖了这个区间,所以答案是准确的。
代码
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,x,y,f[100001][22];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)scanf("%d",&f[i][0]);//初始化,因为从第i个数开始长度为1的区间的最大值就是它本身
for(int j=1;j<=20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
while(m--)
{
scanf("%d%d",&x,&y);
int k=log2(y-x+1);
printf("%d\n",max(f[x][k],f[y-(1<<k)+1][k]));
}
}