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频数的主要内容,如果未能解决你的问题,请参考以下文章

九度oj 题目1397:查找数段

带有红宝石集合/可枚举的酷技巧和富有表现力的片段[关闭]

BitTorrent:发送请求的最佳速率?

如何制作频数分布表?

频数分布直方图的特点是啥

R语言怎么按组距300编制频数表