题目大意
给一个长度为n的不降序列a1,a2,a3,…,an,有q个询问,每个询问为:i j
询问在子序列ai…aj中出现最多的元素。
数据范围:1 <= n, q <= 100000
分析
将原序列转换一下,
if (a[i]==a[i-1])
f[i]=f[i-1]+1;
else
f[i]=1;
对于每个询问(l,r),分为两个部分,前半部分求与a[l]相同的数的个数直到t,后半部分从t开始直接用RMQ对f数组求解最大值就行了。
最后结果为max(前半部分,后半部分)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int n,m,nm;
int d[200001][21];
int f[200001][21];
int p[202001];
int a[202001],b[202001],c[202001];
int max(int x,int y)
{
if (x<y)
return y;
else
return x;
}
void init()
{
scanf("%d",&n);
if (n==0)
return;
scanf("%d",&m);
memset(a,0,sizeof(a));
memset(d,0,sizeof(d));
memset(f,0,sizeof(f));
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
c[i]=a[i];
}
}
void dp()
{
for (int i=1;i<=n;i++)
{
if (a[i]==a[i-1])
d[i][0]=d[i-1][0]+1;
else
d[i][0]=1;
f[i][0]=a[i];
}
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
{
if (i+(1<<j)-1>n) break;
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
if (d[i][j]==d[i][j-1])
f[i][j]=f[i][j-1];
else
f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
int main()
{
while (0==0){
init();
if (n==0) return 0;
dp();
for (int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
int ans2=0;
int j;
for (j=a;j<=b;j++)
{
if (c[a]==c[j])
ans2++;
if (c[a]!=c[j])
break;
}
int ans;
a=j;
if (a>b)
{
printf("%d\n",ans2);
continue;
}
int k=floor(log(b-a+1)/log(2));
ans=max(d[a][k],d[b-(1<<k)+1][k]);
ans=max(ans,ans2);
printf("%d\n",ans);
}
}
}