嗯,RMQ问题。
纠结了好久,不过总算弄懂了
@。@
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100000+10;
const int MANX_LOGN=20;
int a[MAXN],left[MAXN],right[MAXN],num[MAXN];
struct RMQ
{
int d[MAXN][MANX_LOGN];
void init(const vector<int> &X)
{
int n=X.size();
for(int i=0;i<n;i++) d[i][0]=X[i];
for(int j=1; (1<<j) <=n;j++)
for(int i=0; i + (1<<j) -1 <n; i++)
d[i][j]=max(d[i][j-1],d[i + (1<<(j-1))][j-1] );
}
int query(int L,int R)
{
int k=0;
while( 1<<(k+1) <= R-L+1)
k++;
return max(d[L][k],d[R - (1<<k) +1][k]);
}
};
RMQ rmq;
int main()
{
int n,q;
while(scanf("%d", &n) ,n)
{
scanf("%d",&q);
vector<int>cnt;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
a[n]=a[n-1]+1; //最后一段通过它来标记
int begin=0,kind=0;
for(int i=0;i<=n;i++)
{
if(a[i]>a[i-1]) //新的一段
{
cnt.push_back(i-begin);
for(int j=begin;j<i;j++)
{
num[j]=kind;
left[j]=begin;
right[j]=i-1;
}
begin=i;
kind++;
}
}
rmq.init(cnt);
while(q--)
{
int L,R;
scanf("%d%d",&L,&R);
L--;R--; //本题从1开始
int ans;
if(num[L]==num[R])
ans=R-L+1;
else
{
ans=max(right[L]-L+1,R-left[R]+1);
if(num[L]+1 < num[R])
ans=max(ans,rmq.query(num[L]+1,num[R]-1));
}
printf("%d\n",ans);
}
}
}

本文深入探讨了RMQ问题的解决方法,并提供了一个具体的实现案例。通过预处理数组,可以快速查询区间最大值,有效提高了算法效率。
456

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



