这一道题的题意是说给出一段序列,然后任给一段区间,求此区间出现最多的数字的数目。
比如:
给一段序列: 10 3 12 12 8 8 8 8 8 7 11 11
然后,所给区间为:
2,4 则出现最多的数字的数目为2
3,10 则出现最多的数字的数目为5
此题需要对原数列进行处理,如果f[i] == f[i-1],那么,f[i] == f[i-1] + 1;
若f[i]!=f[i-1],那么f[i]=1;
然后,对给定的区间用rmq处理,但是,这个给定的区间也需要进行处理。
例如:对上边的数列来说,给定区间7,12,假如不处理区间,那么计算rmq_search(7,12);则得到的结果是5,明显是不对的。
所以需要处理该区间,把此区间分为2个部分,7-9,10-12,对于第一部分,计算该部分的数字数量,然后对第二个区间进行rmq.
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define max_n 100010
int num[max_n];
int f[max_n];
int max_f[max_n][20];
int n;
void init()
{
int i,j,k;
for(i=1;i<=n;i++)
max_f[i][0] = f[i];
for(j=1;(1<<j)<=n;j++)
{
for(i=1;i+(1<<j)-1<=n;i++)
{
max_f[i][j] = max(max_f[i][j-1],max_f[i+(1<<(j-1))][j-1]);
//printf("%d ",max_f[i][j]);
}
//printf("\n");
}
}
int rmq_search(int l,int r)
{
if(l>r)
return 0;
int k = (int)log2(r-l+1.0);
return max(max_f[l][k],max_f[r-(1<<k)+1][k]);
}
int main()
{
int q,i,a,b;
while(scanf("%d",&n)&&n)
{
scanf("%d",&q);
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
if(i==1)
{
f[i]=1;
//cout<<f[i]<<" ";
continue;
}
if(num[i]==num[i-1])
{
f[i] = f[i-1] + 1;
}
else
{
f[i] = 1;
}
}
init();
for(i=1;i<=q;i++)
{
scanf("%d%d",&a,&b);
int t = a;
while(t<=b&&num[t]==num[t-1])
{
t++;
}
int cnt = rmq_search(t,b);
//cout<<cnt<<endl;
int ans = max(t-a,cnt);
printf("%d\n",ans);
}
}
return 0;
}