码迷,mamicode.com
首页 > 其他好文 > 详细

【OJ1801】频数

时间:2018-08-02 02:09:05      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:ext   pre   har   ==   string   题目   const   lin   while   

1801 -- 频数(Solution)

题目大意 : 给定一个包含 \(n\) 个元素的序列 \(A\) 和若干询问 \(l,r\),求出 \(A_l\sim A_r\) 出现次数最多的数的频数。保证给定的序列元素单调不降。

Tag: RMQ

Analysis By LC:

将询问区间分为左中右三个部分,左和右分别为未完全包含在询问区间里的元素,分别单独求解;中间是完全包含,用 \(\text 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\n",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\n",ans);
    }
}

【OJ1801】频数

标签:ext   pre   har   ==   string   题目   const   lin   while   

原文地址:https://www.cnblogs.com/farway17/p/9404510.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!