简介
假如我们要求区间的最大值,怎么办(用一位数组搞定)?
没事,我们有RMQ。
今天略讲讲RMQ的ST算法,非常水,希望大家都能学会。
略讲
DP
我们设
Fi,j
表示
区间[i,i+2j−1]
的最大值。
对于状态转移,我们可以将区间
[i,i+2j−1]
看作
[i,i+2j−1−1]
和
[i+2j−1,i+2j−1]
两个区间。
状态转移方程显然为
Fi,j=max(Fi,j−1,Fi+2j−1,j−1)
询问
对于询问,我们只需要
O(1)
解决。
我们只需要询问两端区间的最大值,设
M=log2r−l+1
,则这两端区间是
[l,r−2M]
和
[r−2M+1,r]
。
代码
随手打的,随便看看,理解一下。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int f[1005][10],i,j,m,l,r,n,q,ans;
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&f[i][0]);
for(j=0;j<=log2(n);j++)
for(i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1)),j-1]);
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&l,&r);
m=log2(r-l+1);
ans=max(f[l][m],f[r-(1<<m)+1,k]);
printf("%d\n",ans);
}
}