题意
给出一个序列,求某一个区间的最大值。(RMQ)
思路
ST算法,设f[i][j]f[i][j]表示从序列的第ii个位置开始个数的最大值,我们可以得到公式f[i][j]=max(f[i][j−1],f[i+2j−1][j−1])f[i][j]=max(f[i][j−1],f[i+2j−1][j−1]),相当于把一个从ii到的区间分成了两个长度为2j−12j−1的区间。当我们查询最大值的时候,我们可以算出一个kk,就是让这个区间长度时,kk的最大值,那么我们查询的区间的答案就为max(f[l][k],f[r−2k+1][k])max(f[l][k],f[r−2k+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]));
}
}
772

被折叠的 条评论
为什么被折叠?



