RMQ经典题,游程编码之后进行RMQ查询区间最值,loc[i]表示位置i是第几段,cot[i]表示第i段的数的个数,L[i]表示i所在段的最左边,R[i]表示i所在段的最右边,查询时分两种情况:
(1) l,r区间里的数在同一段,答案为r-l+1.
(2)不在同一段 答案为R[l]-l+1,r-L[r]+1,RMQ(loc[R[l]+1],loc[L[r]-1])的最大值
代码如下:
/*************************************************************************
> File Name: RMQ.cpp
> Author: acvcla
> QQ:
> Mail: acvcla@gmail.com
> Created Time: 2014年10月06日 星期一 13时29分38秒
************************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<cstdlib>
#include<ctime>
#include<set>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define pb push_back
int dp[maxn][20],A[maxn],L[maxn],R[maxn],loc[maxn],cot[maxn];
void Init(int n){
for(int i=1;i<=n;i++)dp[i][0]=cot[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)<=n;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
}
int RMQ(int l,int r)
{
if(l>r)return 0;
int k=0;
while(1<<(k+1)<=r-l+1)k++;
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
int n,m;
while(cin>>n){
if(!n)return 0;
cin>>m;
A[0]=999999999;
int cnt=0,l=1;
rep(i,1,n){
cin>>A[i];
if(A[i]!=A[i-1]){
R[i]=i;
++cnt;
cot[cnt]=1;
int k=i-1;
while(k>=l){
R[k--]=i-1;
}
L[i]=l=i;
}else{
cot[cnt]++;
L[i]=l;
R[i]=i;
}
loc[i]=cnt;
}
int k=n-1;
while(k>=l){
R[k--]=n;
}
int r;
Init(cnt);
while(m--){
cin>>l>>r;
int ans=0;
if(loc[l]!=loc[r]){
ans=max(R[l]-l+1,r-L[r]+1);
ans=max(ans,RMQ(loc[R[l]+1],loc[L[r]-1]));
}else ans=r-l+1;
cout<<ans<<endl;
}
}
return 0;
}