P9460 众数 I

思路

这道题可以改序列的 \(k\) 个数,问有多少个数字可以变成众数。

那么我们可以检查每个数字,来判断这个数字是否可以在序列被更改后作为众数。

从最优的思路出发,我们每次肯定是把数量最多的一个数字变成想要的数字,这样才能保证进行的操作最少,但是需要考虑的是原序列出现最多次数的数字可能不止一个,比如序列:\(1,1,1,2,2,2\),出现了三次的数字有两个,所以判断条件也绝对不是 \(num[i]+k>=maxn-k\)

而还需要注意的是,序列里不仅仅有出现次数最多的数字,还有次多的数字,所以想要 \(O(1)\),判断每个数字是否可行是几乎不可能的,我们只能从模拟的思路出发,每次将当前数字的数量加上目前最多数的个数,然后将目前最多数 \(-1\)(代表每个最多数都拿一个给i),再加上目前最大数原本的个数,直到操作次数被用完为止。

赛时代码(有点乱qwq)

#include<bits/stdc++.h>
using namespace std;
int n,k,a[1000005],num[1000005],nnum[1000005],maxn,ans,nn;
int main()
{
    cin>>n>>k;
    if(k>=n){cout<<"pigstd";return 0;}//小特判,不过应该不用的。
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        num[a[i]]++;//第一次桶排,统计出每个数字出现的次数
    }
    for(int i=1;i<=n;i++)
    {
        if(maxn<num[i]) maxn=num[i],nn=1;else if(maxn==num[i]) nn++;//统计最多次数和最多的有多少个数字
        nnum[num[i]]++;//统计每个出现次数的出现次数(桶排的桶排)
    }
    if(k<=nn)//分了个类,如果满足条件,则操作数用完最大次数要么不变,要么就是原来的减一,这样的话就和原来次多的数无关了
    {
    	if(k>=maxn-k/nn){cout<<"pigstd";return 0;}//判断原来有0个的数字可不可以变成众数,如果可以就代表所有数都可以变成众数。
    	for(int i=1;i<=n;i++)
    	{
        	if(num[i]+k>=maxn-k/nn) ans++;//判断这个数可不可以成为众数。
    	}
    	cout<<ans;return 0;
    }
    int tk=k,tmax=maxn,u,tn;//tk:临时k,tmax:临时最大值,u:当前数的数量,tn:当前最多数的个数
    for(int i=1;i<=n+1;i++)
    {
        tk=k,tmax=maxn,u=num[i],tn=nn;//更新最新的消息
        if(u>=tmax){ans++;continue;}//如果当前数量已经超过了最多数量的话,这个数是可以变成众数的。
        while(tk)
        {
            if(u>=tmax){ans++;if(num[i]==0){cout<<"pigstd";return 0;}break;}//判断同上,特判了0(好像没用,比赛时考虑不了那么多,随手就写上去了qwq
            if(tk<tn){//如果没办法把当前所有的最多数变成i。
                u+=tk;
                if(u>=tmax){ans++;if(num[i]==0){cout<<"pigstd";return 0;}break;}//立马判断一次,因为此时所有的操作数都用完了。
                else break;
            }
            u+=tn,tk-=tn,tmax--,tn+=nnum[tmax];//相当于每个当前最多数拿一个变成i后的各项数值,自己推一下就知道了。
            if(!tk)
            {
            	if(u>=tmax){ans++;if(num[i]==0){cout<<"pigstd";return 0;}}
                break;
            }//如果操作数是0了,就再判一次,因为下次没办法判了。
        }
    }
    if(ans==n+1){cout<<"pigstd";return 0;}//再特判,如果n+1(因为题中给了最大就是n)可以成为众数,那么所有数都可以
    cout<<ans;
    return 0;
}
posted @ 2023-08-22 20:00  One_JuRuo  阅读(15)  评论(0编辑  收藏  举报