【Note】贪心
感谢 $ \text{orzws/chy} $ 倾情授课。
贪心与动态规划的一个使用条件是无决策后效性。这个我暂时不大理解,没法写总结
然后就是贪心的一些证明方式。听说很多时候贪心是猜后证明的,然后我可以不证明 对拍试试正确性是么.jpg
-1. 证明方式
微扰:见下 排序贪心;
反证法;
数学归纳法;
局部最优作用范围扩展不会使得整体更劣;
决策包容性:作出局部最优决策后,问题状态空间中的可达集合包含了作出其他任何决策后的可达集合。见下 反悔贪心。
0. 朴素贪心
AT2557 [ARC073C] Ball Coloring
所有球中标的最大与最小值一定会被选中,根据此分类讨论。
钦定 \(max\) 取红色,若:
\(min\) 取蓝色。那么剩下的贪心,小的给蓝,大的给红。
\(min\) 取红色。那么剩下的枚举最小值然后二分最大值,经典求最小极差法。
P2587 [ZJOI2008]泡泡堂
大型田忌赛马(?)
爷的做法:
暴力 \(set\) 日一下()
优先拿小的去日。
题解做法:
最好的情况是,优先用弱的去赢弱的,打不过就看最强的能不能打过最强的,不行就替补()
最坏的情况是,把两支队伍反过来就可以了。
1. 排序
既然是排序我们就需要关键字。
大致做法是这样的。只考虑相邻两者交换的影响,列不等式求解,得到需要用来排序的关键字。
或者说假设一个最优解,将最优解的邻项交换,看看答案会不会变劣。
(这个叫邻项交换法,也叫微扰?)
AT2672 [AGC018C] Coins
既然有三个选项,不妨缩成两个()
假设全都选了金币(\(A\))
设 \(f_i=B_i-A_i\),\(g_i=C_i-A_i\)
现在就要选 \(y\) 个人选 \(f\) , \(g\) 个人选 \(g\) 。
考虑 \(i\) ,\(j\) 两者, \(i\) 选 \(f\) , \(j\) 选 \(g\) 比 \(i\) 选了 \(g\) , \(j\) 选了 \(f\) 更优,则:
\]
即:
\]
所以按 \(f-g\) 排个序就好了。
P2123 皇后游戏
忘了先讲国王游戏辽。
皇后游戏中,大臣获得的奖金数目是递增的,我们要使得\(c_n\)尽可能小。
影响\(c_i\)的只有\(c_{i-1}\),前\(i-1\)个数的顺序并不产生额外影响。前缀子问题最优可推到全局最优。
考虑邻项\(i\),\(j\)交换。设\(i\),\(j\)的前一个获得奖金为\(K\),他们前面所有人的\(a\)值和为\(S\),则:
- 当\(i\)在\(j\)之前时:
\]
\]
- 当\(j\)在\(i\)之前时:
\]
\]
当\(i\)在前比\(j\)在前更优:
\(max\{K+b_i+b_j,S+a_i+b_i+b_j,S+a_i+a_j+b_j\}<max\{K+b_i+b_j,S+a_j+b_i+b_j,S+a_i+b_i+a_j\}\)
\(k+b_i+b_j\)那项可以直接去掉了。对于剩下的项,取负再加上\(S+a_i+b_i+a_j+b_j\),得到:
\]
经过一系列我看不下去的证明,这个比较是有传递性的。

听说直接把这个比较扔进cmp函数也能过。我感觉会\(RE\)(?)
严格弱序
std::sort中比较符必须有的性质,具体如下:
非自反性(自己跟自己比较为false)
非对称性(若x与y比较为true,则y与x比较为false)
传递性(若x与y比较为true,y与z比较为true,则x与z比较为true)
不可比性的传递性(若x与y互相比较为false,y与z互相比较为false,则x与z互相比较为false)

对,他是没有不可比性的传递性的。
优化的话,由于\(a\)的前缀和可能影响全局答案,优先把\(a\)较小的放前面。
证不动正确性了。;w;
P1248 加工生产调度
2. 数据结构维护相关信息
3. 反悔贪心
贪心的时候,需要注意的是,一定只考虑相邻一步的操作。一些题目确实需要把看起来多样繁琐的操作拆成单位简单操作叠加作用的结果。
仔细思考了一下反悔贪心的原理。一般来说需要一个优先队列,来存储接着某项直接操作/反悔操作的增益
这种贡献是逐步累加的,直到大根堆堆头 $ \leq 0 $ 。
重新百度了一下((),反悔贪心大致是分为反悔堆和反悔自动机。
反悔堆
通过堆来维护当前贪心策略最优解。
USACO09OPEN 工作调度Work Scheduling
有 $ n $ 项工作,每 $ i $ 项工作有一个截止时间 $ D_i $ ,完成每项工作可以得到利润 $ P_i $ ,求最大可以得到多少利润。
比较基础。按照 $ D_i $ 排序,能做的工作就做,然后以 $ P_i $ 作为关键字放入小根堆。遇到不能做的工作,取出堆顶,如果 $ P_i>top $ 就换掉。
CF436E Cardboard Box
反悔堆的一个常见做法。把可行的各种下一步的策略分别放到不同的堆里面。
比如这道题,从 \(i\) 个星星到 \(i+1\) 个星星就有如下取法:
从未取星星的一关 \(i\) ,获取一个星星,代价 \(a_i\);
从取了一颗星星的一关 \(i\),再获取一个星星,代价 \(b_i-a_i\);
从取了一个星星的一关 \(i\),把星星扔回去,取另一个未取星星一关 \(j\) 的两个星星,代价 \(b_j-a_i\);
从取了两个星星的一关 \(i\),把星星扔回去一个,取另一个未取星星一关 \(j\) 的两个星星,代价 \(b_j-(b_i-a_i)\)。
每次取代价最小一个就行了。
具体的实现细节上,维护的是:
未取星星关的 \(a_i\)(操作1);
未取星星关的 \(b_i\)(操作3,4)
取一星星关的\(b_i-a_i\)(操作2);
取一星星关的\(-a_i\)(操作3);
取两星星关的\(a_i-b_i\)(操作4)。
要把堆中不符合 \(type\) 的数值 \(pop\) 掉。可以看一下这位的实现,写的不错(?)
AT2672 [AGC018C] Coins
重新再看一下这个题。
假设先任意选择。对于三个不同选择的人 \(i\) \(j\) \(k\),反悔的操作可能有:
\(i \longleftrightarrow j\) (\(B_i-A_i+A_j-B_j\))
\(j \longleftrightarrow k\) (\(C_j-B_j+B_k-C_k\))
\(i \longleftrightarrow k\) (\(C_i-A_i+A_k-C_k\))
\(i \longrightarrow j \longrightarrow k \longrightarrow i\) (\(B_i-A_i+C_j-B_j+A_k-C_k\))
\(i \longrightarrow k \longrightarrow j \longrightarrow i\) (\(C_i-A_i+B_k-C_k+A_j-B_j\))
具体的维护:
选了 \(A\) 的 \(B_i-A_i\),\(C_i-A_i\)
选了 \(B\) 的 \(A_i-B_i\),\(C_i-B_i\)
选了 \(C\) 的 \(A_i-C_i\),\(B_i-C_i\)
反悔自动机
一般是过程中累积贡献,通过差值消去中间项(反悔)来快速得到全局最优解。
CF865D Buy Low Sell High
基本的贪心思路是:买入价格最小的股票,在能赚钱的时候卖出。
当然这个是错的()
之前也写过一个类似的题目(纪念品/股票市场),由于一天之内价格不会变动,所以可以假装我们先卖了,然后再买进来,之后再卖掉。对于 $ i \leq j \leq k $ ,具体的表现形式是:
$ (p_k-p_j)+(p_j-p_i)=p_k-p_i $
先买入 $ i $ ,再在 $ j $ 卖出,获得 $ p_j-p_i $ 的贡献。然后对于 $ j $ ,接下来有两步可能的操作:
在 $ p_j $ 又买回来,再往后考虑。
在 $ p_j $ 又买回来(相当于在 $ j $ 啥都没干)后,再买 $ p_j $ 。
于是我们可以在队列里面塞两遍 $ p_j $ 。
如果贡献加了一次 $ p_k-p_j $ ,表示 $ j $ 反悔,在 $ i $ 买在 $ k $ 卖;
如果贡献加了一次 $ p_{k_1}-p_j $ ,再加一次 $ p_{k_2}-p_j $ ,表示 $ j $ 先反悔,再 $ j $ 买 $ k_2 $ 卖。
P1792 [国家集训队]种树
反悔自动机,做法是把所有选项扔进堆里,取出堆头 $ b $ ,把与 $ b $ 相邻的两项 \(a\),\(c\) 合成一个新点 \(a+c-b\),再扔回堆里面。
看完题解还是纠结了半天两个问题:
这个反悔存储方式是否覆盖了所有可能的下一步
或者未存储的反悔策略不可能成为最优的答案

浅列了一下情况。
【Note】贪心的更多相关文章
- OJ题解记录计划
容错声明: ①题目选自https://acm.ecnu.edu.cn/,不再检查题目删改情况 ②所有代码仅代表个人AC提交,不保证解法无误 E0001 A+B Problem First AC: 2 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- CF733C Epidemic in Monstropolis[模拟 构造 贪心]
C. Epidemic in Monstropolis time limit per test 1 second memory limit per test 256 megabytes input s ...
- CF732D. Exams[二分答案 贪心]
D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...
- CodeForces 485C Bits[贪心 二进制]
C. Bits time limit per test1 second memory limit per test256 megabytes inputstandard input outputsta ...
- leetcode bugfree note
463. Island Perimeterhttps://leetcode.com/problems/island-perimeter/就是逐一遍历所有的cell,用分离的cell总的的边数减去重叠的 ...
- UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...
- CF722D. Generating Sets[贪心 STL]
D. Generating Sets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 【CodeForces 589F】Gourmet and Banquet(二分+贪心或网络流)
F. Gourmet and Banquet time limit per test 2 seconds memory limit per test 512 megabytes input stand ...
- hdu5037 Frog (贪心)
http://acm.hdu.edu.cn/showproblem.php?pid=5037 网络赛 北京 比较难的题 Frog Time Limit: 3000/1500 MS (Java/Othe ...
随机推荐
- latex常用的宏包(转载)
页面与标题式样 geometry 利用 geometry 可以很方便的设置页面的大小.由于可以自动居中排放页面,自动计算并平衡页面各部分如页眉.页脚.左右边空等的大小,因此只需给出很少的信息就能得到满 ...
- vue中模块化后mapState的使用
代码如下: 相当于声明了一个变量name,然后以state入参取得其modules文件夹中user文件里的name属性.因为在模块(如user)中,在抛出时的export default中添加了一句: ...
- LeetCode 之 111. 二叉树的最小深度
原题链接 思路: 递归计算每个子树的深度,返回左右子树中深度小的值: 由于题目中要求的是到最近叶子节点的深度,所以需要判断 左右子树为空的情况: python/python3: class Solut ...
- django_模板层的变量和标签
一.模板层的变量 1.能传递到模板层的数据类型:str(字符串).list(数组).dict(字典).obj(类实例化的对象).fun(函数)等. 2.在模板中使用变量的方法: (1)字符串:{{ 变 ...
- RKO组——冲刺随笔(2)
这个作业属于哪个课程 至诚软工实践F班 这个作业要求在哪里 第五次团队作业:项目冲刺 这个作业的目标 记录冲刺计划.要求包括当天会议照片.会议内容以及项目燃尽图(项目进度) 1.昨日进展 已开始着手模 ...
- 艾思软件app开发公司帮您分析:开发一个APP多少钱?
首先你要知道你所要开发的APP, 是不是已经成熟的相同的产品, 如果有的话那还是建议直接购买, 这种已经能满足你需求的成品APP价格会很便宜, 总成本一般也就1到2万的级别. 如果没有那就需要定制开发 ...
- Angular架构学习
定义 Angular 是一个用 HTML 和 JavaScript 或者一个可以编译成 JavaScript 的语言(例如 Dart 或者 TypeScript ),来构建客户端应用的框架. 写 An ...
- liunx 目录详解
/etc/sysconfig/network-scripts/ifcfg-eth0 第一块网卡的配置文件 /etc/sysconfig/network 主机名配置文件 /etc/profile ...
- 制作带curl命令的容器
创建一个容器,启动后使用curl命令请求指定的地址 方法一.固定的地址,创建Dockerfile前先修改entrypoint.sh里的地址 vi entrypoint.sh#! /bin/bashcu ...
- 修改/编辑jar包
替换或者导入jar包时,jar包被自动压缩,springboot规定嵌套的jar包不能在被压缩的情况下存储. 解决(本文以升级ojdbc包为例): 使用jar命令解压jar包,在压缩包外重新替换jar ...