想要一个房间,带有落地窗。摆一张双人床,一个小书桌。早晨醒来,喜欢的人睡在旁边,随时看窗外风景,有灵感了便在小书桌上写写画画,没事的时候摆弄摆弄花草,傍晚 灯光昏暗透过落地窗可以盯着夕阳发呆 想想明天吃什么。平平淡淡地过完一生,碌碌无为也没有关系。

​ ----向往的生活

题目描述

给一个数组,一共有 img个数。
你能进行最多 img次操作。每次操作可以进行以下步骤:

选择数组中的一个偶数 ai,将其变成 ai/2。

现在你进行不超过 img次操作后,让数组中所有数之和尽可能小。请输出这个最小的和。

题目分析

题目要求在进行不超过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;
}