本题需要用堆来动态管理最大的偶数。

可以用优先队列或multiset实现。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define sc(x) scanf("%lld", &(x))
int main() {
    ll ans = 0, n, k, a;
    priority_queue<ll> q;
    sc(n), sc(k);
    while (n--) {
        sc(a);
        ans += a;                   //先把所有的数加起来
        if (a % 2 == 0) q.push(a);  //所有的偶数进优先队列
    }
    while (!q.empty() && k--) {  //还有偶数而且次数没用完
        ll now = (q.top() / 2);
        ans -= now;  //执行一次操作
        if (now % 2 == 0) q.push(now);
        q.pop();
    }
    printf("%lld\n", ans);
}

学习@19zhaoyang的multiset写法:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define sc(x) scanf("%lld", &(x))
int main() {
    ll n, m, x;
    sc(n), sc(m);
    multiset<ll, greater<ll>> st;
    ll ans = 0;
    for (int i = 1; i <= n; ++i) {
        sc(x);
        if (x & 1)
            ans += x;  //统计奇数
        else
            st.insert(x);  //加入偶数
    }
    while (m && st.size()) {
        int now = *st.begin();
        st.erase(st.begin());  //删除堆顶
        if (now & 1)
            ans += now;  //奇数不消耗次数,加入答案
        else
            st.insert(now / 2), --m;
    }
    for (auto& it : st) ans += it;  //相当于用const &遍历,更高效
    printf("%lld\n", ans);
    return 0;
}