 /**//*
题意:给出一个递增序列,给出询问区间,问出现次数最多是多少
查询次数最大,可以用RMQ
先离散化得到
index[x[i]] 数x[i]是离散化后是第几
start[j] 第j个第一次在x[]出现的位置
f[] 表示出现次数
然后对于查询区间,分3种情况讨论一下!!
*/
#include<cstdio>
#include<cstring>
#include<cmath>

 inline int max(int a,int b) {return a>b?a:b;}

const int MAXN = 100005;

int rmq[MAXN][20],x[MAXN],f[MAXN];
int index[2*MAXN],start[MAXN];
int N,Q,NN;

void initRMQ()
  {
for(int i=1;i<=N;i++)rmq[i][0]=i;
for(int j=1;(1<<j)<=N;j++)
for(int i=1;i+(1<<j)-1<=N;i++)
if(f[rmq[i][j-1]]>f[rmq[i+(1<<(j-1))][j-1]])rmq[i][j]=rmq[i][j-1];
else rmq[i][j]=rmq[i+(1<<(j-1))][j-1];
}

int query(int L,int R)
  {
int iL = index[x[L]] , iR = index[x[R]];
int sL = start[iL],sR = start[iR];
if(iL==iR)return R-L+1;
else if(iL==iR-1)return max(sR-L,R-sR+1);
else
 {
int ans = max(start[iL+1]-L,R-sR+1);
int a = iL+1,b =iR-1 ;
int k = log(1.0+b-a)/log(2.0);
ans = max(ans,max(f[rmq[a][k]],f[rmq[b-(1<<k)+1][k]]));
return ans;
}
}

int main()
  {
int L,R;
while(scanf("%d",&NN),NN)
 {
memset(f,0,sizeof(f));
scanf("%d",&Q);
N = x[0] = 0;
for(int i=1;i<=NN;i++)
 {
scanf("%d",&x[i]);
x[i]+=MAXN;
if(x[i]!=x[i-1])
 {
index[x[i]] = ++N;
start[N] = i;
}
f[N]++;
}
initRMQ();
while(Q--)
 {
scanf("%d%d",&L,&R);
printf("%d\n",query(L,R));
}
}
return 0;
}
|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|