题目链接:传送门
题目大意:给出一个非严格单调递增的序列,然后给出一些查询,在一个区间内重复的数最多出现了几次。
思路:对于序列上的位置i,记录从i开始连续出现了多少个和a【i】相同的数字。
用数组b维护一个后连续重复数的数量。对这个数组b进行RMQ。
然后对于给定的一个查询,将其分为两部分,一部分是后部分,即最右边相等的几个数,他的数量无法用数组b来记录,所以拿出来单独计算,然后用rmq查询前半部分的数量,比较即可。
注意一下,肯定查询的这个区间都是同一个数,那就没有前半部分了。我们使用二分查找后半部分第一个数的位置来判断。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define maxn 100005
int len,Arr[maxn];
int b[maxn];
int F_maxn[maxn][20],F_min[maxn][20];
void RMQ_init()//³õʼ»¯º¯Êý
{
int nlog=(int)(log(double(len))/log(2.0));
for(int i=1;i<=len;i++)
F_maxn[i][0]=F_min[i][0]=b[i];
for(int j=1;j<=nlog;j++)
{
for(int i=1;i<=len;i++)
{
if(i+(1<<j)-1<=len)
{
F_maxn[i][j]=max(F_maxn[i][j-1],F_maxn[i+(1<<(j-1))][j-1]);
F_min[i][j]=min(F_min[i][j-1],F_min[i+(1<<(j-1))][j-1]);
}
}
}
}
int RMQ_Query(int l,int r)
{
int nlog=(int)(log(double(r-l+1))/log(2.0));
int MA=max(F_maxn[l][nlog],F_maxn[r-(1<<nlog)+1][nlog]);
int MI=min(F_min[l][nlog],F_min[r-(1<<nlog)+1][nlog]);
return MA;
}
int fid(int l,int r)
{
int ans=Arr[r];
int mid;
while(l<r)
{
mid=(l+r)/2;
if(Arr[mid]<ans)
{
l=mid+1;
}
else
{
r=mid;
}
}
return r;
}
int main()
{
int query;
while(~scanf("%d",&len)&&len)
{
scanf("%d",&query);
for(int i=1;i<=len;i++) scanf("%d",&Arr[i]);
for(int i=len;i>=1;i--)
{
if(i==len)
{
b[i]=1;
}
else
{
if(Arr[i]==Arr[i+1])
{
b[i]=b[i+1]+1;
}
else
{
b[i]=1;
}
}
}
RMQ_init();
while(query--)
{
int l,r;
scanf("%d%d",&l,&r);
int temp=fid(l,r);
//cout<<temp<<"++"<<endl;
int ans=r-temp+1;
r=temp-1;
if(l>r)printf("%d\n",ans);
else printf("%d\n",max(ans,RMQ_Query(l,r)));
}
}
return 0;
}