(第四场)G Maximum Mode 【YY+暴力】

链接:https://www.nowcoder.com/acm/contest/142/G

来源:牛客网

题目描述

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.

case:

input:

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

output:

-1
3
3
3
4

题目大意:

给N个数, 删掉M个数,使得剩下的数众数最大,求那个众数。

官方题解:

•枚举答案,考虑需要删⼏几个数才能使之变成众数

•出现次数多余它的都要被删到次数比它小

•剩下的随便便删

大概思路(本人理解):

枚举出现的次数,因为出现次数多的更有可能成为众数,所以从多到少枚举出现的次数,其次就是相同出现次数的话取最大的那个(也有可能是由比它出现多的减过来的),简单来说就是用M次删除把最大的那个众数弄出来。

不过要注意一点就是:优化输入!!!本人没有优化输入前TLE了五次,当然,这里包括了更傻的每个案例都重新定义映射和动态数组,想这样省略初始化,但是太慢了。。。还是老老实实初始化的好。(哎,都在代码里了)

AC code:

#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long int
using namespace std;

const int MAXN = 1e5+10;

ll a[MAXN]; ///原序列
ll c[MAXN]; ///c[x]出现次数为 X 的最大值
ll T_case, N, K;
vector<ll> num_len[MAXN];   ///出现次数为 X 的数有多少个
map<ll, ll> mmp;     ///记录出现次数

inline ll read()                      ///优化输入
{
    register ll c = getchar(), flag = 1, sum = 0;
    while(c > '9' || c < '0')
    {
        if(c == '-') flag = -1;
        c = getchar();
    }
    while(c <= '9' && c >= '0')
    {
        sum = sum*10+c-'0';
        c = getchar();
    }
    return flag*sum;
}

int main()
{
    scanf("%lld", &T_case);
    while(T_case--)
    {
        N = read(); K = read();
        mmp.clear();
        for(ll i = 0; i <= N; i++)
        {
            num_len[i].clear();
            c[i] = 0;
        }

        for(int i = 1; i <= N; i++)
        {
            a[i] = read();
            if(mmp.count(a[i]) == 0) mmp[a[i]] = 1;
            else mmp[a[i]]++;
        }

        for(int i = 1; i <= N; i++)
        {
            ll x = mmp[a[i]];             ///a[i]出现的次数
            if(x)
            {
                num_len[x].push_back(a[i]);    ///增加出现次数为 x 的元素
                c[x] = max(c[x], a[i]);        ///更新出现次数为 X 的最大值
                mmp[a[i]] = 0;                 ///出现次数清零,避免重复加
            }
        }
        ll res = -1;  ///当前满足成为众数的最大值
        ll pre = 0;   ///使当前的数成为众数的需要的删除次数
        ll ans = -1;   ///答案
        for(int len = N; len > 0; len--)   ///枚举出现次数
        {
            ll xx = num_len[len].size();  ///出现次数为len的数量
            pre+=xx;
            if(xx)
            {
                res = max(res, c[len]);   ///当前的众数有可能由上一个众数退化而来
                if(pre-1 <= K)            ///如果剩余的删除次数满足需要删除次数的条件
                {
                    ans=max(ans, res);    ///更新答案
                }
                else break;               ///剩余的删除次数无法满足当前长度众数的要求的,那之后的也无法满足了
            }
            K-=pre;
            if(K<0) break;  ///无剩余操作次数
        }
        printf("%lld
", ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ymzjj/p/9384796.html