洛谷 P7713 打分

1 P7713 打分

2 题目描述

时间限制 \(100ms\) | 空间限制 \(128M\)

\(A\) 去参加奥运会。

奥运会中共有 \(n\) 名裁判,分别给小 \(A\) 打分 \(a_1,a_2,\ldots,a_n\)

\(A\) 对自己的得分不满意,于是他将某名裁判打出的分数加 \(1\),称为一次操作。

但是小 \(A\) 不能太贪心,他最多只能进行 \(m\) 次操作。

\(A\) 的最终得分为:所有得分中,去掉一个最高分和一个最低分后的平均值。

\(A\) 想知道,他的最终得分最高为多少。

数据范围:\(3≤n≤10^5,0\le m,a\le 10^9\)

3 题解

考虑贪心。

我们发现,由于最小的值和最大的值都会被去掉,所以我们肯定不能给最小值增加。考虑到这一点,我们可以先将这个数组从小到大排序,然后从第 \(2\) 个小的数开始到第 \(n - 1\) 数小的数,每个数都补到最大的数一样大。

这个时候,我们如果还剩下一些可以加的数,就不能单纯地加到中间的那 \(n - 2\) 个数上了,因为这样中间的数会成为新的最大值。所以我们需要将 \(n - 1\) 个数一起增加,最后再将其中一个去掉才行。容易发现,假设这时我们还剩下 \(m\) 次增加的机会,我们可以给这 \(n - 1\) 个数一起增加 \(\lfloor \dfrac{m}{ n- 1} \rfloor\) 轮,对答案的贡献就是 \(\lfloor \dfrac{m}{n - 1} \rfloor * (n - 2)\)

这时,我们发现如果还有一些剩余的机会,这些机会就可以给这 \(n - 1\) 个数中的任意几个增加,最后再减去一就是贡献,形式化地,就是:\((m \mod n - 1) -1\)。当然如果这里 \(m \mod n - 1 = 0\),我们就不用 \(-1\)

4 代码(空格警告):

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
#define int long long
int n, m, ans;
int a[N];
int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return x * f;
}
signed main()
{
    n = read(), m = read();
    for (int i = 1; i <= n; i++) a[i] = read();
    sort(a+1, a+n+1);
    for (int i = 2; i <= n-1; i++)
    {
        ans += a[i] + min(m, a[n] - a[i]);
        if (m < a[n] - a[i]) m = 0;
        else m -= (a[n] - a[i]);
    }
    ans += (m / (n - 1)) * (n - 2);
    if (m % (n - 1) > 1) ans += (m % (n-1) - 1);
    printf("%lld", ans);
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-07-12 22:32  David24  阅读(270)  评论(0编辑  收藏  举报