优先队列贪心
要最大化使用天数,需每次选择当前不舒适度最小的口罩:
- 初始时所有口罩的不舒适度为原始值,优先选最小的用(单日成本最低);
- 用完后该口罩不舒适度翻倍,重新加入候选队列,下次仍选当前最小的。
- 直到选择下一个口罩的不舒适度会导致总不舒适度超过
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最大为1e9,m最多约30 * 1e5 = 3e6,整体效率可满足题目要求(n ≤ 1e5)。 - 空间复杂度:
O(n),堆中最多存储n个元素(所有口罩)。

京公网安备 11010502036488号