洛谷 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;
}