想要一个房间,带有落地窗。摆一张双人床,一个小书桌。早晨醒来,喜欢的人睡在旁边,随时看窗外风景,有灵感了便在小书桌上写写画画,没事的时候摆弄摆弄花草,傍晚 灯光昏暗透过落地窗可以盯着夕阳发呆 想想明天吃什么。平平淡淡地过完一生,碌碌无为也没有关系。
----向往的生活
题目描述
给一个数组,一共有 个数。
你能进行最多 次操作。每次操作可以进行以下步骤:
选择数组中的一个偶数 ai,将其变成 ai/2。
现在你进行不超过 次操作后,让数组中所有数之和尽可能小。请输出这个最小的和。
题目分析
题目要求在进行不超过k次操作后,让所有数之和尽可能小,那么利用贪心的思想,我们每一次操作都对当前数组中最大的数进行操作,这样经过k次之后就能求出最小之和,在这里我们需要两个东西,一个是需要自动排序的功能的数组,一个是要动态的加入当前数组中,那么由此我们可以想到优先队列,定义一个大根堆,每次操作的时候把当前堆顶的元素取出来,操作之后,我们把新的元素加进队列,这样就始终维护一个大根堆,进行k次操作之后,就能得到最小值
AC代码
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5 + 5; int n, k; ll a[maxn]; priority_queue<int, vector<int>, less<int> >q; int main() { scanf("%d%d", &n, &k); ll ans = 0; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); if (a[i] & 1) ans += a[i]; else q.push(a[i]); } while (!q.empty() && k) { int now = q.top(); q.pop(); now /= 2; k--; if (now & 1) ans += now; else q.push(now); } while (!q.empty()) { ans += q.top(); q.pop(); } printf("%lld\n", ans); return 0; }