CF2182E New Year's Gifts 题解
2025 最后一天来写题解祭
思路
贪心。我们先将 \(val_i = z_i - y_i\),\(k = k - \sum y_i\),代表先给每个人买价值为 \(y_i\) 的礼物,还需要给 \(val_i\) 的价值就可以使第 \(i\) 个人高兴。
首先把礼盒用完肯定最优。从大到小依次枚举 \(val_i\),如果有礼盒可用,就用美丽值 \(\ge val_i\) 的最小美丽值的礼盒。这样更大的礼盒就可以用来满足其他的礼物。可以用 multiset 维护每一个礼盒,直接二分即可。对于剩下的礼盒,从小到大依次枚举 \(val_i\),只要钱还够用就买。
时间复杂度 \(\mathcal{O}(n \log m)\),可以通过本题。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
struct node
{
int x, val;
} b[N];
int t, n, m, k;
int a[N];
bool cmp(node x, node y)
{
return x.val > y.val;
}
bool cmp2(node x, node y)
{
return x.val < y.val;
}
void solve()
{
scanf("%lld%lld%lld", &n, &m, &k);
for (int i = 1; i <= m; i++)
scanf("%lld", &a[i]);
for (int i = 1, y, z; i <= n; i++)
{
scanf("%lld%lld%lld", &b[i].x, &y, &z);
b[i].val = z - y;
k -= y;
}
sort(b + 1, b + n + 1, cmp);
multiset<int> ms;
for (int i = 1; i <= m; i++)
ms.insert(a[i]);
int ans = 0;
for (int i = 1; i <= n; i++)
{
auto it = ms.lower_bound(b[i].x);
if (it == ms.end()) continue;
b[i].val = 2e9;
ans++;
ms.erase(it);
}
sort(b + 1, b + n + 1, cmp2);
for (int i = 1; i <= n; i++)
{
if (b[i].val < 2e9 && k >= b[i].val)
{
ans++;
k -= b[i].val;
}
else break;
}
printf("%lld\n", ans);
}
signed main()
{
scanf("%lld", &t);
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号