牛客网暑期ACM多校训练营(第四场)G Maximum Mode(模拟+思维)

链接:https://www.nowcoder.com/acm/contest/142/G
来源:牛客网
 

Maximum Mode

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

The mode of an integer sequence is the value that appears most often. Chiaki has n integers a1,a2,...,an. She woud like to delete exactly m of them such that: the rest integers have only one mode and the mode is maximum.

输入描述:

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains two integers n and m (1 ≤ n ≤ 105, 0 ≤ m < n) -- the length of the sequence and the number of integers to delete.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) denoting the sequence.
It is guaranteed that the sum of all n does not exceed 106.

输出描述:

For each test case, output an integer denoting the only maximum mode, or -1 if Chiaki cannot achieve it.

示例1

输入

复制

5
5 0
2 2 3 3 4
5 1
2 2 3 3 4
5 2
2 2 3 3 4
5 3
2 2 3 3 4
5 4
2 2 3 3 4

输出

复制

-1
3
3
3
4

题意:给你n个数,删除m个数,使得剩下的数出现次数最多的数(众数)最大。

思路:利用结构体储存每一种数个数的 个数cum 最大值val,如果要使b[i].val成为众数所需要减去的个数 sum(前缀和)

        再用m跟sum比较 遍历一遍,取最大值;

代码:

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int val;///数值
    int num;///数量
    int sum;///要使其为众数,需要减掉的数量
}b[100005];
bool cmp(node a,node b)
{
    return a.num<b.num;
}
int ncase,n,k;
int a[100005];
int main()
{
    while(~scanf("%d",&ncase))
    {
        while(ncase--){
            scanf("%d %d",&n,&k);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            sort(a+1,a+n+1);///对n个数进行排序
            int tot=0;///一共有多少种数
            int cnt=0;///数量
            for(int i=1;i<n;i++){
                if(a[i]!=a[i+1]){
                    b[++tot].val=a[i];
                    b[tot].num=cnt+1;
                    cnt=0;
                }
                else cnt++;
            }
            b[++tot].val=a[n];
            b[tot].num=cnt+1;//记录val 数量
            sort(b+1,b+tot+1,cmp);///按数量从小到大排序
            b[1].sum=n-b[1].num-(tot-1)*(b[1].num-1);//如果要使b[1].val成为众数所需要减去的个数
            int sum1=b[1].num;///储存i成为众数之前 不需要删除 的数量
            cnt=2;///储存i之前不需要删除的数有几个
            for(int i=2;i<=tot;i++){
                if(b[i].num==b[i-1].num){///如果数量与前一个相等,那么要删除的也相等
                    b[i].sum=b[i-1].sum;
                    sum1+=b[i].num;//储存i之前不需要删除的数量
                    cnt++;
                }
                else{
                    sum1+=b[i].num;
                    b[i].sum=n-sum1-(tot-i)*(b[i].num-1);//让 b[i].val 变成众数所需减去的个数
                    cnt++;
                }
            }
            int ans=-1;
            for(int i=1;i<=tot;i++){///遍历找到最优解
                if(b[i].sum<=k)
                    ans=max(b[i].val,ans);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

思路二:用map记录每种数出现的次数,用vector[i]统计存出现i次的数有哪一些,Mxa[i]记录出现i次的最大值的数,从次数 n次到1次依次用 m跟所需删去的前缀和pre 枚举每个值,符合条件就取最大值。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int n,m,k;
int a[maxn];
int Mxa[maxn];
vector<int>vc[maxn];
int ans,ct,cnt,tmp,flag;
map<int,int>mp;//mp[i][j] 数值i有j个;
void init(int n)
{
    mp.clear();
    for(int i=0;i<=n+5;i++)
    {
    vc[i].clear();
    Mxa[i]=0;
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
       cin>>n>>m;
        init(n);//清空为0
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            if(mp.count(a[i])==0)mp[a[i]]=1;
            else mp[a[i]]++;//数量++
        }
        for(int i=1;i<=n;i++)
        {
         int x=mp[a[i]];//数量
         if(x) {
             vc[x].push_back(a[i]);//数量 数值
             Mxa[x]=max(Mxa[x],a[i]);//  该数量 数值的 最大值
             mp[a[i]]=0;
             }
        }
        int ma=-1;
        int pre=0;
        ans=-1;
        for(int i=n;i>0&&m>=0;i--)//个数从大到小枚举
        {
            int xx=vc[i].size();//个数为xx
            pre+=xx;//前面的个数前缀和
            if(xx){//如果有
            ma=max(ma,Mxa[i]);//取最大值
            if(pre-1>m)//是否可以取
                break;
            }
        ans=max(ans,ma);
        m-=pre;
        }
        printf("%ld\n",ans);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41668093/article/details/81311769