从CF1935C看带反悔的贪心和multiset

Problem - C - Codeforces.

1|0思路

首先很显然对 b 数组排序能最小化 b 的花费。

难点在 a 的选择,因为已经对 b 排序,不可能再兼顾 a 的优劣,所以 a 需要类似枚举的技术,这是一个类似搜索最优子集的问题,可以用 DP,但是更可以贪心

带反悔的贪心

这类问题就是尽可能的取最优的,一旦发现不符合条件了,就反悔,把已选择中的最劣的逐出方案。

这题是可以这样做的,因为 b 排序之后,对于每个要枚举的起点 L,哪怕把其中一个方案逐出了,也只要减去这个方案的 a 值即可,因为 b 值恒等于 RL 的差。

针对本题,对于每一个 L 起点,都不停的选后方的 a ,一旦不符合条件,就把已选择的最大的 a 逐出方案。

2|0实现

  • 我们需要一个数据结构来维护 a 的最大值,支持删除插入。
    • std::multiset
      • extract
        • 删除,且迭代器不失效
      • *rebegin()
        • 取最大
      • 相较于std::priority_queue
        • 能同时维护最大值和最小值,且支持访问

3|0代码

struct Message { int a, b; }; void solve() { int n, l; std::cin >> n >> l; std::vector<Message> arr(n); for (int i = 0; i < n; i++) std::cin >> arr[i].a >> arr[i].b; std::sort(all(arr), [&](auto& x1, auto& x2) { if (x1.b == x2.b) return x1.a < x2.a; return x1.b < x2.b; }); int ans(0); for (int L = 0; L < n; L++) { std::multiset<int> S; int cur(0); for (int R = L; R < n; R++) { S.insert(arr[R].a); cur += arr[R].a; while(!S.empty() and arr[R].b - arr[L].b + cur > l) {//一旦不符合条件,就反悔 int max_value(*S.rbegin()); cur -= max_value; S.extract(max_value);//精确删除元素,避免迭代器失效 } ans = std::max(ans, sz(S));//维护出以L起点取到的最大值 } } std::cout << ans << '\n'; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/18056210.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示