优先队列贪心

要最大化使用天数,需每次选择当前不舒适度最小的口罩

  • 初始时所有口罩的不舒适度为原始值,优先选最小的用(单日成本最低);
  • 用完后该口罩不舒适度翻倍,重新加入候选队列,下次仍选当前最小的。
  • 直到选择下一个口罩的不舒适度会导致总不舒适度超过k为止。

数据结构选择

使用小顶堆(优先队列) 维护当前所有口罩的不舒适度,能高效获取并弹出最小值(时间复杂度O(logn)

代码

#include <bits/stdc++.h>
using namespace std;
signed main()
{
    int n, k;
    cin >> n >> k;
    // 小顶堆:存储当前所有口罩的不舒适度,堆顶是最小值
    priority_queue<int, vector<int>, greater<>> p;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        p.push(x); // 初始时将所有口罩的原始不舒适度入堆
    }

    //  贪心计算最大天数
    int ans = 0, sum = 0; // ans记录天数,sum记录总不舒适度
    while (1)
    {
        int t = p.top(); // 取当前不舒适度最小的口罩
        p.pop();

        // 检查使用该口罩是否会超总阈值
        if (sum + t > k)
        {
            break; // 超阈值,无法使用,退出循环
        }
        // 可用:更新总不舒适度和天数
        sum += t;
        ans++;
        // 该口罩用完后翻倍,重新入堆(可重复使用)
        p.push(t * 2);
    }

    cout << ans << endl;
    return 0;
}

复杂度分析

  • 时间复杂度O(m logn),其中m是最终的天数(最多为log2(k/min(a_i)) * n),每次堆操作(弹出 / 插入)的时间为O(logn)。由于k最大为1e9m最多约30 * 1e5 = 3e6,整体效率可满足题目要求(n ≤ 1e5)。
  • 空间复杂度O(n),堆中最多存储n个元素(所有口罩)。