题目链接:https://ac.nowcoder.com/acm/problem/213140

到主站看:https://blog.csdn.net/weixin_43346722/article/details/109688868

题目

给一个数组,一共有 个数。
你能进行最多 次操作。每次操作可以进行以下步骤:
选择数组中的一个偶数 ,将其变成
现在你进行不超过 次操作后,让数组中所有数之和尽可能小。请输出这个最小的和。

输入

第一行输入两个正整数 ,用空格隔开
第二行输入 个正整数

输出

一个正整数,代表和的最小值。

样例输入

5 3
2 4 8 10 11

样例输出

24

样例解释

操作 次,对 操作 次,最后的数组是 。可以证明这样的操作是最优的。

数据范围


思路

一道小贪心。

我们很明显可以看出,我们要进行操作是总和变得更小,肯定每一次就是贪心选择最大的偶数进行操作。
(因为这样总和减去的值就会大)

我就直接弄个了堆,把所有偶数丢进去,奇数就直接算进答案里面。
然后每次把最大的拿出来 ,如果变成了奇数,就直接算进答案里面,否则就重新把除了之后的数塞进去。

然后最后把堆里的数加进答案,就可以了。

然后如果堆空了(就是所有数都变成了奇数),那就直接退出,不用枚举 次那么多。

代码

#include<queue>
#include<cstdio>
#include<algorithm>

using namespace std;

priority_queue <int> a;
int n, k, x;
long long ans;

int main() {
    scanf("%d %d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        if (x & 1) ans += (long long)x;
            else a.push(x);
    }

    while (k && !a.empty()) {
        x = a.top();
        a.pop();
        x /= 2;
        if (x & 1) ans += (long long)x;
            else a.push(x);
        k--;
    }

    while (!a.empty()) ans += (long long)a.top(), a.pop();

    printf("%lld", ans);

    return 0;
}