贪心基础 - 学习笔记
贪心基础 - 学习笔记
主要记录下做到的贪心题
打 *
的是我认为有一定难度的题,*
越多难度越大
持续施工中……
贪心整合包 (easy)
ABC103D
题意为给定
转化为经典区间覆盖模型
这是一个比较典的贪心模型,我们将所有区间 按照右端点排序 (按照左端点排序可能出现一个区间完全包含另一个区间的情况,不好分析,因此选择按右端点排序),贪心可知对于每个区间,若其不满足要求则 删去最右端的点 一定最优
实现时维护最靠右的删除点位置即可
ABC137D
转化下题意,给定
无法直接确定当前工作干或不干 (有截止日期限制,不好定序)
悔贪,维护最劣操作替换
很典的悔贪,我们将工作按照截止日期排序,建立 小根堆 维护之前选择干的工作;对于每个工作:
- 如果在其截止日期前能干掉(即小根堆元素个数
)则直接将其报酬插入堆中 - 反之,取出小根堆堆顶
,若 则说明将之前的工作替换为当前工作更优, ,弹出堆顶并将 插入堆中
ABC123D
题意为给定三个数组
数太多没法直接排序
考虑从已知数推出下一个数
容易发现一个感性理解很对的做法:将
- 输出堆顶并将其弹出
- 设堆顶为
,将 插入堆中
由于总共只会向堆中加入
考虑简单证明,设堆顶包含
P3619
题意为给定
容易发现
的任务能做就做 考虑分类 发现是定序问题,考虑临项交换
考虑将所有任务按照
- 若
,显然我们能做就做,将其按照 从小到大排序依次做,做不了则无解 - 若
,考虑 临项交换法- 设我们原本的完成任务序列为
,则需要满足 与 - 若交换
则需要满足 与 - 由于此时
递减,若 或 则必然无解,换不换没有区别;其次,无论换不换,完成这两个任务后都有 ,对之后没有影响,因此我们只需要使完成第二个任务的可能性最大 - 综上,若交换则必然有
即 ,因此我们按照 从大到小排序最优
- 设我们原本的完成任务序列为
按照上述策略分类并排序后模拟即可
*P2431
题意为给定
题目明示从二进制角度考虑
无法直接确定当前选择是否更优 考虑调整法 (实质是悔贪)
观察数列的形式,容易想到从 二进制 的角度考虑;大致考虑递减,而一次操作 消掉多个
将
考虑证明这么做的正确性,显然选择
AGC004D
题意为有
分析并转化题意
发现当前最优决策即为最优 (可以用调整法证) 直接贪心即可
先分析下为什么每个点走
因此问题转化为修改其他点的出边使得其在
综上,每次我们找到 深度最大 的点,向上跳
*CF525D
题意为给定一个只包含 .
与 *
的矩阵,要求将最少的 *
改为 .
使得所有 .
的联通块都构成矩形(联通块可以不止一个),求最少更改数量
分析题目性质
结论:更改一格中的 *
为 .
的充要条件是 在一个包含该格的 *
首先,如果出现这种情况必然需要更改该格,有充分性;另外,若更改所有上述情况中的 *
后仍有残缺的 .
矩形,在该矩形的四角处必然会出现上述情况,矛盾,因此有正确性
实现时可以对于每个要改的 *
做 dfs,边改边搜即可,注意要搜八连通
*AGC007B
题意为给定
从简单情况考虑
考虑如何推广
直接构造似乎并不好做,我们循序渐进,先考虑简单情况
首先考虑是否可以构造
现在我们尝试对每个
于是问题转化为使得每个
P.S. 这道题启示我们若直接做不好做,可以 先从弱化版考虑,逐渐推至正解
P2209
旅行家问题:你有一辆油箱容量为
注意到当前最优决策即为最优
首先,显然需要将加油站按距离排序;为方便做题,我们可以将起点视作
首先判断无解情况,显然是你加满了油也开不过去:
- 当你在起点且下个加油站离你超过
单位距离 - 当你不在起点且下个加油站离你超过
单位距离
其次考虑贪心,显然我们 总是往最便宜的走;因此首先找到能走到的(距离
- 不是当前加油站,直接走过去即可,油不够就加到刚好能过去
- 是当前加油站,先加满油,再找到剩下能走到的加油站中最便宜的并走过去
直接模拟即可
贪心整合包 (medium)
诶你怎么全打星啊
*P2751
有
- 使所有工件都受过 A 型机器加工的最晚时间最小值
- 使所有工件都受过 B 型机器加工的最晚时间最小值
第一问好做,当前最优决策即为最优
考虑套用结论解决第二问 发现不对,考虑错因 从简单版本考虑问题 进行推广
对于第一问,每个工件到达时间相同,能越早加工就越早加工,肯定总是贪心地选择 最早的空闲 A 型机器;因此可以使用小根堆维护所有 A 型机器的最早空闲时间点,每次取出队头
对于第二问,每个工件到达时间不同,第一问的贪心策略不再适用(例如我们可以先用次优的 B 型机器加工先到的工件,再用最优的机器加工后到的工件)
还是 先从简单版本考虑,如果只有一台 B 型机器,完成时间有何规律?不妨设
输出
因此,我们仍然可以采用第一问的方法得到前
*P3076
题意为在一个长度为
考虑拆贡献
分析过程,推导性质 考虑过程带来的影响
首先,显然我们一定要走过
考虑接客的过程;直接从上一个牛的终点匹配最近的起点是不对的,因为我们可能会半路扔下当前牛,先去送另一头牛再回来接该头牛;显然我们 只会在有牛的地方扔下牛
为方便叙述,不妨设扔下的牛为
这同样也是一个较为经典的贪心问题,同样直接给出结论:将
P5521
题意为给定一棵
发现是对儿子的定序问题
临项交换
考虑设
因此,我们需要比较
- 左式在
取 max,则 ,不需要交换,成立 - 左式在
取 max,则需保证 ,即
综上,按照
*CF549G
题意为给定
- 若
,则令 ,最后交换 与
若最终能够使整个序列非降,则输出最终序列;否则输出 :(
发现与排序有关
分析题目性质,寻找不变量
注意到序列非降与排序有关,考虑寻找操作中的 不变量;如果
此时做法就非常显然了,将
P.S. 这道题启示我们发掘变化中的不变量可能有奇效
*CF798D
题意为给定两个长度为
消去
转化题意,考虑分组
注意到题目的要求实际上等价于选出的数之和大于其余数之和;考虑 两两分组,令
由于我们两两分组且每组中都选了
P.S. 这道题启示我们遇到
**P7831
好题!
题意为给定一个
分析题目性质
发现 dp 式子 考虑为什么不能转移,进而考虑消环 拓扑排序 考虑对于环如何更新答案 发现应从最大边入手,这契合我们的观察
现要求旅行商可以永远不停地走下去,对于每个点,求从该点出发满足上述要求时旅行商至少要有多少初始资产
首先考虑 调整法,先将初始资产
观察题目性质,注意到:
取 时可以在整个图上畅通无阻,因为报酬 ;同时这启示我们 从大到小考虑边- 不妨设
为点 的答案,显然可得转移柿子 ;但是不能直接 dp,因为原图中可能有环
既然有环导致不能转移,我们考虑 消环,使用 拓扑排序 的思想
- Key Observation:走向原图中出度为
的点没有意义
类似拓扑排序,我们开一个队列
- 若
非空,取出队首 ,遍历反图中的边 ,若 未被删且 ,则按照上述 dp 转移柿子用 更新 ;由于 这条边的意义只在于可以通过 更新 ,现在它的使命已经完成了,可以将边 删去,若此时 的出度为 则将其入队 - 若遍历完
后边 仍未被删除,则说明从 只能走到出度非 点,即 走到一个环;由于我们从大到小考虑边,走到的环中的 一定 ,因此此时只需要初始资产为 即可畅通无阻,用 更新 ;最终删去 ,若 出度为 则将其入队
类似拓扑排序,每个点只会入队一次,时间复杂度
P.S. 这道题启示我们将不同的算法思想结合
P8113
题意为给定
- 若
则令 - 反之,则令
求最终所有可能得到的
注意到这是定序问题
临项交换
观察样例,大概可以猜测取最大值时将序列 从小到大排序,取最小值时将序列 从大到小排序
记经过前
-
- 不交换时,
处贡献为 , 处贡献有可能为 - 交换时,
处贡献为 , 处贡献有可能为
又由于
,不交换时贡献为 的可能性最大;如果不交换时贡献 ,交换后贡献 ,确实可能会导致后面某处不交换时贡献 ,交换后贡献 ,但 再往后 相同,因此 不会更劣 - 不交换时,
-
- 不交换时,
处贡献为 , 处贡献为 - 交换时,
处贡献为 , 处贡献为
此时无论换不换对
的总贡献都是 - 不交换时,
-
- 不交换时,
处贡献为 , 处贡献可能为 - 交换时,
处贡献为 , 处贡献可能为
又由于
,不交换时贡献为 的可能性最大;至于是否会导致后面更劣与第一种情况类似,这里不再赘述 - 不交换时,
综上,从小到大排序最优;取最小值时证明类似
**P3045
题意为有
分析朴素贪心错因
发现无法确定当前最优决策是否总最优 考虑悔贪 希望使变量最小,因此对优惠券而非牛反悔 整理策略,比较相似处,进而优化写法
容易想到一个简单贪心:将所有优惠价格与普通价格排序,之前没买过该牛就选上;但是自己造几组数据就能发现这个贪心是假的,例如:
3 2 6
2 1
3 1
5 2
为什么假了?牛二的优惠券价格相比牛三更优,但实际上选择牛二就买不了牛三;相比之下牛三省钱更多,省下来的钱正好可以再买牛二
这启示我们进行 反悔贪心;注意到如果对买的牛反悔,带来的变量太多,价格、所买牛数都会变化,过程较为复杂,因此不妨选择 对用过的优惠券反悔;这意味如果之前在一头牛身上用优惠券,对其反悔时只转移其身上的优惠券,仍然用原价购买该牛,因此 买过的牛只增不减
考虑对于两头牛
- 不转移,总价格为
- 转移,总价格为
综上,转移时要求
由于我们不考虑转移优惠券,选择用优惠券一定是全场最优;因此,我们应该将 当前转移优惠券最便宜 (每次取优惠价最便宜的牛)与 当前原价最便宜 (每次取原价最便宜的牛)进行比较,总结一下贪心策略:
- 按照
分别扔进小根堆 ,同时开小根堆 记录买过的牛的 - 每次取出
进行比较,则优惠的差价为- 若
,直接买 - 若
,此时如果有优惠券则直接买 ,若没有优惠券:- 若
则买 - 反之,转移优惠券
- 若
- 若
事实上我们还可以继续改进贪心策略;注意到比较
总结一下改进后的贪心策略:
- 按照
分别扔进小根堆 ,同时开小根堆 记录买过的牛 - 每次取出
进行比较:- 若
则买 - 反之,转移优惠券
- 若
P.S. 这道题启示我们固定状态以简化转移策略,同时可以比较转移策略中相似之处以寻找优化方式
*P1484
题意为有
分析朴素贪心错因
发现无法确定当前最优决策总最优 考虑悔贪 设计为相同问题,实现自动反悔
直接从大到小贪的问题是可能选到相邻的;注意到对于位置
为实现上述操作,可以考虑采用 模拟链表 的方式实现
*P2893
题意为给定
发现不好直接刻画变化结果
分析变化过程 推导性质,基于性质考虑下一步做法
考虑分析变化的性质;不妨设
,此时无须改动, ,此时可以选择:- 将
上调至 ,即令 - 将
上调一部分(可以不上调),再将 下调(因为下调 会连带着导致之前一部分也下调);此时问题变为选择一个数 使得 取 min,易知 为 的中位数
- 将
综上,可以发现
有了这个结论,我们考虑 dp;以非降情况为例,设
直接做是
Bonus:如果需变为严格递增序列,可以在一开始令
Bonus:如果只需变为非降序列且要求时间复杂度
此时由于选择的
实现时只需要维护大根堆,时间复杂度
P.S. 这种做法的精髓是保留更改的不确定性,只把贡献先累加
*P3620
题意为给定
稍作分析可以得到不可能同时选择形如
将原数组差分,转化为 选择
*CF865D
题意为有一个商品,第
不好判断当前最优决策是否总最优
考虑悔贪 设计反悔策略,实现自动反悔
由于最后你手上没有商品,每一个买入的商品最终都会对应在某天卖出;不妨考虑第
考虑 引进新的物品 刻画反悔操作,即需要创造一个价格为
,即
注意到这个式子与“第
- 考察是否能够购买堆顶 (即
),可以则购买并将 插入堆中 - 将
插入堆中(注意与上一步是独立的)
**P3162
题意为有
从简单情况入手
考虑如何推广 考虑如何优化朴素过程 发现仅需包含最优解,推导包含最优解的性质
首先考虑如果已经知道离
因此,我们有:
直接枚举可得
对于每个零件编号
考虑反面,不妨设存在先后两次替换为
不妨设最优时
同理可得
综上,我们有
实现时直接模拟即可
**P1248
题意为需要加工
注意到是定序问题
临项交换 不好直接推,不妨从简单情况考虑 发现不满足不可比性的传递性 分析决策性质,考虑从极端情况入手
首先 从简单情况入手,考虑只有两个产品的情况;此时:
- 先加工产品
再加工产品 ,代价为 - 交换,代价为
注意到
此时一个显然思路是按照上述策略直接排序;很不幸这是错的,因为原式在 临项取等 时可能出现问题
- 比如
,其虽然满足 与 ,但是不满足
这个式子虽然不支持直接排序,但从极端情况入手能发现一些比较好的性质
Key Observation1:该不等关系下,若
同理,若考虑
Key Observation2:该不等关系下,若
这启示我们将
- 若最小值在
取到,则 ,在第 个加工 - 若最小值在
取到,则 ,在第 个加工
最终按照确定好的加工顺序模拟即可
P.S. 这道题启示我们临项交换法有时需要特殊考虑取等(好像叫不可比性的传递性),同时有时从极端情况入手可以发现有用性质
*CF436E
题意为有
无法确定当前最优决策是否总最优
考虑悔贪 推导变化过程,设计策略使得能够自动反悔
可以很明显的看出是悔贪,不过这道题稍有区别;普通悔贪一般只有两个选择(反悔与否),这道题的选择数量相对较多,具体的,我们考虑 增加一颗星的方式:
- 选择一个没玩过的关卡
,该关卡选择 - 选择一个选
的关卡 ,该关卡改选 - 选择一个选
的关卡 ,该关卡不选,另在一个没玩过的关卡 选择 - 选择一个选
的关卡 ,该关卡改选 ,另在一个没玩过的关卡 选择
综上,我们需要维护:
的小根堆,对应第一种方式 的小根堆,对应第二种方式 的大根堆与 的小根堆,对应第三种方式 的小根堆与 的小根堆,对应第四种方式
实现起来细节较多,需要仔细考虑增删关系
*CF1601D
题意为有
- 若
,则他登山成功,令 - 反之,他登山失败,无事发生
注意到是定序问题
临项交换 发现 的大小关系会对 产生影响 考虑分类,两类内部的贪心策略是显然的 考虑两类间的临项交换,大力分讨即可 注意特殊情况
现在需要为这
注意到
,对于一对 ,登山成功时有 ,我们希望山的高度最小,因此 按 从小到大排序 ,对于一对 ,登山成功时有 ,同理 按 从小到大排序
接下来考虑两类情况之间的影响,不妨设有
,选 先更优 ,选 先更优 ,此时只能选一个,先选 则 ,先选 则 ,显然选 先更优 ,选 先更优 ,选 先更优 ,此时选 先必然能都取到,选 先更优
观察选取的性质,可以发现每组中的最大值都不取;因此考虑 按照
为什么能多登就多登一定更优?在这么排序的前提下,如果后面的
需要特别注意,此时取等不意味着可以随便排;取等时,情况 1、2、6 仍要求先选
综上,我们按照
*P4785
题意为给定
注意到题目表述贴近二叉树,转到树上考虑
分析选择策略,发现难点只在于选 时 的顺序 首先考虑模拟,注意到时间复杂度可以接受,直接记忆化即可
注意到
对于
最小,显然什么都不做最优 最小,显然只交换 最优 最小,此时 号点上的值需要为 ,但 的两个儿子的值可以随意调换;儿子怎么放最优,取决于 与 最终会被换到哪里去
情况 3 似乎不太好直接看出来;没关系,注意到 可能从点
具体的,记
,则我们将 换到 上- 反之,我们将
换到 上
为什么?因为无论我们怎么换,对于
对于
时间复杂度
*CF351E
题意为给定长为
分析变号操作带来的影响
推导题目结论 依照结论设计策略
由于可以任改符号,初始时可令
Key Observation:对于
- 若
取正,无论 怎么取都有 ; - 若
取负,无论 怎么取都有
这启示我们 从大到小 考虑
直接模拟,时间复杂度
Bonus:可以发现对于第
*ARC073C
题意为有
不妨给一定出现在这四个值中的值定色
分类讨论,推导策略
不妨设
-
将全局 min 编号染为蓝色,显然对于每个包将
染红、 染蓝最优 -
将全局 min 编号染为红色,此时不妨考虑若 确定
该如何染色:- 对于
,不成立 - 对于
,只能将 染蓝 - 对于
, 将 染蓝最优
观察上述策略,容易发现实际上是根据
与 的大小关系 分类;考虑按照 从小到大排序,则答案必然形如将 前一段的 染蓝( 除外)、后一段的 染蓝( 除外),直接扫一遍枚举分界点维护即可 - 对于
**AGC034C
给定非负整数序列
简化题意,消去变量
尝试调整分析性质 首先考虑暴力,发现时间复杂度可以接受,于是直接枚举即可
题目看上去有点复杂,考虑如何简化;不妨设
时,应令 ,有 时,应令 ,有
由于
- Key Observation:当同时存在
与 ,将系数较大者 ,较小者 总会更优
由这一关键性质,我们可以得到所有
注意到
考虑初始令所有
实现时可以用前缀和维护变化量,时间复杂度
ARC147E
题意为有
题目明示需要分类
最小化变劣的影响
考虑分为
但是如果
注意
实现时可以考虑:
- 对
类开一个 的大根堆 - 对
类开一个 的大根堆 - 对
类开一个整体关于 的大根堆 - 对满足
的 单独开一个关于 的小根堆
**P7078
题意为有
- 实力最强的蛇
选择吃掉实力最弱的蛇 , , 退出接下来的操作,之后立即进行下一轮操作 - 实力最强的蛇
选择不吃掉实力最弱的蛇 ,操作立即结束
每条蛇都希望在自己不被吃的前提下,吃掉尽可能多的蛇(它不会吃掉自己);假设每条蛇都足够聪明,求最终会剩下几条蛇
模拟题目过程推导性质
上 trick 维护
Key Observation:在最强蛇
由这一性质,考虑对每轮操作进行分类讨论:
不为下一轮最弱蛇,则蛇 必然选择吃掉蛇 ;这是因为若之后的最强蛇 选择吃掉最弱蛇 ,必然有 ,蛇 必然嘎在蛇 之前,而蛇 既然选择吃就代表它不会嘎,那么蛇 也不会嘎,不吃白不吃 为下一轮最弱蛇,则需要考察下一轮最强蛇 会不会选择吃,这是一个 相同的问题;不妨设都选择吃的情况下递归 轮后出现情况 或只剩两条蛇,此时第 轮的最强蛇不会吃、第 轮会吃……对于 ,若 为偶数则会吃,为奇数则不会吃;这种情况下操作必然在当前轮或下一轮结束
综上,我们边模拟边记录当前是否出现过情况
注意到一开始的关键性质,这启示我们原蛇和形成的新蛇都具有 单调性(进入情况
每次的最大蛇即为
时间复杂度
策略总结
对于邻项交换法:
- 常应用于定序问题
- 直接推式子过于复杂时可以考虑从简单情况入手
对于反悔贪心:
- 常应用于无法确定当前最优决策是否总最优时
- 考虑将原问题刻画为许多相同操作,通过局部最优性保证从当前情况的最优解到下一情况的最优解变化不会很大
- 有时需要确定 "不变量",一般稳定变化,直到达到目标情况 (如目标为选
个数,"不变量"可能为每次反悔后稳定增加 个数)
P.S. 反悔贪心的正确性:
证明存疑。笔者想的也不大清楚
- 考虑反证法,每一步进行归纳,只需要证明当前反悔决策在下一步最优解中即可
- 如果反悔决策不在最优解内:
- 最优解中必定有一个其他决策
- 你在设计反悔策略时保证了反悔策略涵盖所有从的当前步推到下一步的决策
- 由于反悔决策每次按照局部最优执行,其相对当前步的任意其他决策都更优;因此我们考虑将最优解中那个其他决策替换为当前反悔决策,必定更优
- 你考虑将那个其他决策设置为与当前反悔决策冲突的决策,保证可以选择当前反悔决策
一些分析方法:
- 首先考虑暴力的时间复杂度是否可以接受,如果可以则直接模拟
- 分析暴力操作过程 / 分析朴素贪心的错因,进而发掘题目性质,推导贪心策略
- 从简单情况入手后推广 / 从极端情况入手分析性质 有时很有用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】