RMQ问题:range minimum query。还是利用二分的性质。初始化复杂度是nlogn,查询是logn,本题要先编码,然后再利用RMQ的方法来做。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstdio>
using namespace std;
#define N 100005
#define LOGN 30
int Count[N], num[N], Left[N], Right[N];
int d[N][LOGN];
int n, fp, sum, m, cur, pre, q, Max, l ,r;
void RMQ_init(int n)
{
//j=0
for (int i=0;i<n;i++) d[i][0]=Count[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 RMQ(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]);
}
void del()
{
scanf("%d",&pre);
fp=0;
sum=1;
m=0;
num[0]= Left[0] =0;
for (int i=1;i<n;i++) {
scanf("%d",&cur);
if (cur==pre) sum++;
else {
Count[m++]=sum;
for (int j=fp;j<i;j++) Right[j]=i-1;
fp=i;
sum=1;
pre=cur;
}
num[i]=m;
Left[i]=fp;
}
for (int j=fp;j<n;j++) Right[j]=n-1;
Count[m++]=sum;
}
int main()
{
freopen("1.in","r",stdin);
scanf("%d",&n);
while (n!=0) {
scanf("%d",&q);
del();
RMQ_init(m);
for (int i=0;i<q;i++){
scanf("%d%d",&l,&r);
l--;r--;
if (num[l]<num[r]) {
Max=max(Right[l]-l+1,r-Left[r]+1);
if (num[l]+1<num[r]) Max=max(Max,RMQ(num[l]+1,num[r]-1));
printf("%d\n",Max);
}
else {
printf("%d\n",r-l+1);
}
}
scanf("%d",&n);
}
return 0;
}