2019ICPC亚洲区域赛沈阳网络赛F - Honk's pool(贪心&模拟)

93 篇文章 0 订阅
58 篇文章 1 订阅

题目链接:https://nanti.jisuanke.com/t/41406
时间限制:1000毫秒 内存限制:262144K

Problem Description

As we all know, Honk has nn pools, numbered as 1 1 1 ~ n n n. There is a i a_i ai liters water in the i i i-th pool. Every day, Honk will perform the following operations in sequence.

  1. Find the pool with the most water (If there are more than one, choose one at random) and take one liter of water.

  2. Find the pool with the least water (If there are more than one, choose one at random) and pour one liter of water into the pool.

  3. Go home and rest (Waiting for the next day).

Please calculate the difference between the amount of water in the pool with the most water and the amount of water in the pool with the least water after the k k k days.

Input

The input consists of multiple test cases. The input is terminated by the end of file.The number of data sets will not exceed 40

The first line of each test case contains two integers n n n and k k k, which indicate the number of pools and the number of days to operate the pool.

The second line of each test case contains n n n integers, and the i i i-th number represent a i a_i ai indicating the initial amount of water in the i i i-th pool.

1 ≤ n ≤ 500000 1 \le n \le 500000 1n500000, 1 ≤ k ≤ 1 0 9 1 \le k \le 10^9 1k109, 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109.

Output

For each test case, print one line containing the answer described above.

样例输入1

4 100
1 1 10 10

样例输出1

1

样例输入2

4 3
2 2 2 2

样例输出2

0

解题思路

题意: 给你一些水池,k次操作,每次在水量最多的地方取1升水,然后倒到水量最少的地方,求最后最多水量和最少水量的差值。
思路: 我们可以先求出最后的平衡状态,如果k比较大,那么到达平衡状态的时候就是在一个地方取水和倒水。平衡状态有两种:

  1. 一种是总水量可以平分n个水池,那么差值就是0。例如,1 2 3 4 5,最后的平衡状态就是:3 3 3 3 3。
  2. 另外一种就是无法平均的,那么差值就是1。例如,1 3 4 5 6,最后的平衡状态就是:4 4 4 4 3。

而当其k很小,无法使其达到平衡状态的时候,我们就直接模拟,与平衡状态比较,将需要添水的放到一个数组里,然后从最小的开始模拟倒水,求出下边界,然后同样的过程,模拟取水,求出上边界,两者的差值即为答案。

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e5 + 5;
int a[MAXN], b;
int sa[MAXN], sb[MAXN];
int main() {
    int n, k;
    while (~scanf("%d%d", &n, &k)) {
        long long sum = 0, cnt = 0;
        memset(sa, 0, sizeof(sa));
        memset(sb, 0, sizeof(sb));
        int cnta = 0, cntb = 0;
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            sum += a[i];
        }
        sort(a, a + n);
        int m = sum % n, s = sum / n;
        for (int i = 0; i < n; i++) {
            b = s;
            if (m - i > 0) b++;
            if (a[i] < b) {
                cnt += b - a[i];
                sa[++cnta] = a[i];
            }
            else sb[++cntb] = a[i];
        }
        if (k >= cnt) {
            printf("%d\n", m != 0);
            continue;
        }
        int l, r, dep, res = k;
        for (int i = 1; i <= cnta; i++) {
            dep = 1ll * (sa[i + 1] - sa[i]) * i;
            if (dep >= 0 && res > dep)
                res -= dep;
            else {
                l = sa[i] + res / i;
                break;
            }
        }
        res = k;
        for (int i = cntb; i >= 1; i--) {
            long long dep = 1ll * (sb[i] - sb[i - 1]) * (cntb - i + 1);
            if (res > dep)
                res -= dep;
            else {
                r = sb[i] - res / (cntb - i + 1);
                break;
            }
        }
        printf("%d\n", r - l);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ityanger

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值