OJ1801频数
Posted farway17
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OJ1801频数相关的知识,希望对你有一定的参考价值。
1801 -- 频数(Solution)
题目大意 : 给定一个包含 (n) 个元素的序列 (A) 和若干询问 (l,r),求出 (A_lsim A_r) 出现次数最多的数的频数。保证给定的序列元素单调不降。
Tag: RMQ
Analysis By LC:
将询问区间分为左中右三个部分,左和右分别为未完全包含在询问区间里的元素,分别单独求解;中间是完全包含,用 ( ext ST) 表查询最大频数即可。
Code By LC :
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
using std::min;
const int N=100005;
int x[N],f[N][50],n,q,lg[N],sum[N],b[N*2+20];
inline int _read()
{
char c;
int x=0,f=1;
for(; c<'0'||c>'9'; c=getchar())if(c=='-')f=-1;
for(; c>='0'&&c<='9'; c=getchar())x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
int query(int l, int r)
{
int t=lg[r-l+1];
return max(f[l][t],f[r-(1<<t)+1][t]);
}
int main()
{
n=_read(),q=_read();
for(int i=1; i<=n; i++)
{
x[i]=_read();
b[x[i]+N]++; //b[]记录当前元素出现次数
if(x[i]!=x[i-1]) sum[i]=1;
else sum[i]=sum[i-1]+1; //sum[]记录前面有多少元素与当前元素相同
f[i][0]=sum[i];
if(i!=1) lg[i]=lg[i-1]+!(i&(i-1));
}
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j-1)<=n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
while(q--)
{
int l=_read(),r=_read(),ans=0;
if(x[l]==x[r])
{
printf("%d
",r-l+1);
continue;
}
ans=max(sum[r],b[x[l]+N]-sum[l]+1); //右和左的频数
int ll=l+b[x[l]+N]-sum[l]+1,rr=r-sum[r];
if(ll<rr) ans=max(ans,query(ll,rr)); //中的频数
printf("%d
",ans);
}
}
以上是关于OJ1801频数的主要内容,如果未能解决你的问题,请参考以下文章