大概题意:给出一段非降序数组,求出区间 [ l, r ] 的众数
You are given a sequence of n integers a1,a2,...,an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai,...,aj.
Input
The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n,q ≤ 100000). The next line contains n integers a1,...,an (−100000 ≤ ai ≤ 100000, for each i ∈{1,...,n}) separated by spaces. You can assume that for each i ∈{1,...,n−1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the query. The last test case is followed by a line containing a single ‘0’.
Output
For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.
Note: A naive algorithm may not run in time!
Sample Input
10 3 -1 -1 1 1 1 1 3 10 10 10 2 3 1 10 5 10 0
Sample Output
1 4 3
这道题其实跟RMQ差不多,只需要把最小值改成最大值就行了
代码
#include<bits/stdc++.h>
using namespace std;
#define N 100005
int n,q;
int a[N];
int val[N],cnt[N],num[N],lef[N],rig[N];
int d[N][50],len;
void RMQinit() //RMQ算法
{
int i,j;
for(i=1;i<=len;i++)
d[i][0]=cnt[i];
for(j=1;(1<<j)<=len+1;j++)
for(i=1;i+(1<<j)-1<=len;i++)
d[i][j]= max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQquery(int l, int r)
{
int x=0;
while(1<<(x+1)<=r-l+1) //直到区间大于询问区间才可以输出结果
x++;
return max(d[l][x],d[r-(1<<x)+1][x]);
}
int main()
{
int i,l,r;
while(1)
{
scanf("%d",&n);
if(n==0) break;
scanf("%d",&q);
len=1; //len主要是作离散化处理,减少数组占的空间
memset(cnt,0,sizeof(cnt));
scanf("%d",&a[1]);
val[len]= a[1]; //记录每个相同的数字的数值
cnt[len]=1; //记录每个数字的个数
num[1]=len; //num数组也是离散化处理的一部分
for(i=2;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==a[i-1])
{
cnt[len]++;
num[i]=len;
}
else
{
rig[len]=i-1;
len++;
val[len]=a[i];
cnt[len]=1;
num[i]=len;
lef[len]=i;
}
}
RMQinit();
for(i=0;i<q;i++)
{
scanf("%d%d",&l,&r);
if(num[l]==num[r]) //如果询问区间左右两个数字相同,直接输出区间大小即可
printf("%d\n",r-l+1);
else
{
int ans=0;
if(num[l]+1<=num[r]-1) //如果区间左右两个数字相差2及以上就进行查询
ans=RMQquery(num[l]+1,num[r]-1);
ans=max(ans,max(rig[num[l]]-l+1,r-lef[num[r]]+1)); //否则直接判断两个数字哪个个数多
printf("%d\n",ans);
}
}
}
return 0;
}