非递减序列对于区间中出现最多的值出现次数的询问 用到了游程编码 (a,b)表示有b个连续的a。
把原来的序号转化成自定义的序号 然后RMQ 注意特判左右两边多出来的部分。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define M 100005
int num[M],lt[M],rt[M];
int ct[M],d[M][20];
void init(int k)
{
for(int i=1;i<=k;i++) d[i][0]=ct[i];
for(int j=1;(1<<j)<=k;j++)
{
for(int i=1;i+j-1<=k;++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 solve()
{
int n,q;
while(scanf("%d",&n))
{
memset(num,0,sizeof num);
memset(lt,0,sizeof lt);
memset(rt,0,sizeof rt);
memset(d,0,sizeof d);
memset(ct,0,sizeof ct);
if(!n)break;
scanf("%d",&q);
int co=1,a,va;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(i!=1)
{
if(a!=va)
{
va=a;
rt[co]=i-1;
co++;
lt[co]=i;
}
}
else
{
lt[co]=1;
va=a;
}
ct[co]++;
num[i]=co;
}
rt[co]=n;
init(co);
for(int i=1;i<=q;i++)
{
int l,r;
scanf("%d%d",&l,&r);
if(num[l]==num[r]){printf("%d\n",r-l+1);}
else{
if(num[l]+1<=num[r]-1)
{
printf("%d\n",max(rt[num[l]]-l+1,max(rmq(num[l]+1,num[r]-1),r-lt[num[r]]+1)));
}
else
printf("%d\n",max(rt[num[l]]-l+1,r-lt[num[r]]+1));
}
}
}
}
int main()
{
solve();
return 0;
}