其实两个东西都是堆。区别只不过一个是利用差值等巧妙设计等效权值,另外一个则单纯进行判断。html
反悔自动机post
(名字是我本身起的)url
贪心是不能反悔的。由于它就是选择当前的最优解。spa
可是若是当前最优解不是全局最优解怎么办?设计
咱们能够设计一种反悔的方法,而且和贪心的手法结合。htm
使得贪心随便选择,均可以达到正解。blog
姑且叫反悔自动机。get
基本的设计思路是:it
每次选择当前直观上最接近最优解的方案。class
可是发现不对。不是最优子结构
而后想办法怎么支持自动反悔。
0.边有边权,树上选择k个边不相交的路径,总和最大(权值有正有负)
求k次树的直径,每次把直径上的边权取反便可
1.经典问题:CF865D Buy Low Sell High
每次用最小的买入,等到一个能够赚钱的天就卖出。
不对是由于:可能这个买入的股票要等到后面更贵的那一天再卖出。
利用作差,C-A=B-A+C-B,等效转化
用最小的买最大的,而后把差值计入答案,把B放进去两次,再取B为最小的时候,C-B的差值计入ans,至关于用A买入以C卖出
至关于B没有用,因此额外再加入一次B,以防后面须要用B买入再D卖出。
2.相似的:
BZOJ 2151
• 有一个长度为n的环,选择m个两两不相邻的位置。
• 每一个位置都有一个价值Vi,若是选择这个位置就能够获得Vi的价
值。
• 求最大的价值总和,或输出无解。
直观来看,每次选择能选择的最大的价值。
为何不对?由于可能选择了这个最大的,邻居就不能选择。例如1,5,6,5选择了6,就只能再选择1,不如5,5
并且,这个贪心的错误的点就是这里。对于最优解位于其余的位置上的状况,这种贪心都是成立的。
考虑怎么支持反悔。
仍是利用差值。
用双向链表维护相邻的关系。用堆维护全部权值的最大值。
选择了A,把W[L[A]+W[R[A]-W[A]建成一个新的点P,令这个P的L,R分别是:L[L[A]],R[R[A]],而后删掉L[A],R[A],
每次取最大值便可。
由于,若是有a,b,c,d,(紧挨着就是相邻),而且a+c>b+d,那么,就有a+c-b>d
因此,即便咱们先选择了b,可是因为a+c-b>d,咱们会接着选择a+c-b,就至关于选择a+c
反悔堆:
(名字也是我本身起的)(其实就是一个堆)
这个不是无脑地随便贪心了。由于没有什么等效权值的替换。
其实思路差很少。
咱们仍是按照一个贪心策略贪心,而后找出来不足。
想办法反悔。
和反悔自动机不一样的是,这个要人工反悔。
例题: