贪心
反悔贪心
可以看成对于一个错误贪心的修正,使得可以带着反悔/撤回选项。
一般是由两个部分构成,直接选择 \(+\) 反悔。需要对于两个策略都进行设计。
P3620 [APIO/CTSC2007] 数据备份
我们可以发现对于某一位置 \(i\) 来说,如果 \(d_i<\{d_{i-1},d_{i+1}\}\),那么如果要选就是 \(d_i\) 或者 \(\{d_{i-1},d_{i+1}\}\) 打包选。于是如果选中某一位置,直接再插入一个 \(d_{i-1}+d_{i+1}-d_i\) 的选项即可。
CF865D Buy Low Sell High
这其实有点两两匹配的感觉,若干对二元组 \((i,k)\) 表示在第 \(i\) 天买入,第 \(k\) 天卖出。可是我们可能在 \(i<j<k\) 中的 \(j\) 点就匹配到了 \((i,j)\) 怎么办呢?我们可以加入一个反悔操作,\((i,k)=(i,j)+(j,k)\)。
对于每个 \(i\) 我们先看看以堆中最小代价购买,能否通过 \(p_i\) 获利,如果可以就拿出去匹配一下,并加入撤回选项 \(-p_i\),最后要插入一个购买选择选项 \(-p_i\)。
可能会有疑惑,在插入撤销选项了之后为什么还要加入购买选项呢?因为在 \(k\) 处撤销 \((j,i)\) 表示我们匹配了 \((j,k)\),此时 \(i\) 又空闲了,我们还需要一个购买选项。
P3545 [POI2012] HUR-Warehouse Store
能选就选,不能选就找找前面有没有选过 \(b_j>b_i\) 的,替换成 \(b_i\) 显然更优。
P2107 小Z的AK计划
和上一题同理维护即可,注意本题还有路程代价,计算路程代价的时候如果当前时间不够需要一直去除前面的选择直到够用。
P11268 【MX-S5-T2】买东西题
按照 \(a,w\) 降序扫描然后用优惠劵去匹配物品是一个很难搞的方法,我们应该以物品为主体去匹配优惠券。
对于 \(a,w\) 升序排序,用一个队列保存可使用优惠券和可替换优惠券(某个物品改为优惠价然后把券让给后面的物品)可优惠的价格反悔贪心即可。
CF436E Cardboard Box
本题直接选择的策略是花费 \(a_i\) 购买一颗星,和花 \(b_i-a_i\) 再购买第二颗星。
反悔的策略是把一个一星不选,选另一个两星和把一个两星降为一星,选择另一个两星。
由于一星已经放在直接选择的选项里了,所以反悔不需要考虑选择一星。
Johnson 法则
对于邻项交换法中排序不满足不可比传递性,也就是可以通俗理解为排序函数不满足 \(A=B,B=C\),那么 \(A=C\) 的情况。
很经典的案例就是按照 \(\min(a_i,b_j)<\min(a_j,b_i)\) 排序。需要我们分类讨论之后拆开来排序。
例题:P1248 加工生产调度 和 P2123 皇后游戏。
杂题
P9755 [CSP-S 2023] 种树
显然是二分答案天数转化为判定。显然每个点每天高度单调递增,于是长到第 \(r\) 天显然是最优的。于是只需要求出最晚下种天数 \(t_i\) 是否满足 \(h(t_i,r)\ge a_i\)。这个过程同样为二分,\(c_i\) 可能小于 \(0\) 有点难搞,所以这个过程一定要小心讨论,不要乱讨论注意讨论的普适性。
- $ c_i\ge 0 $ 则有 \(\sum\limits_{i=l}^r b_x+ic_x=(r-l+1)b_x+ \frac{(r-l+1)*(l+r)}{2} c_x\)
- \(c_i<0\) ,可以求出 \(i_{max}\) 讨论 \(i_{max}\) 与 \([t_i,r]\) 的关系分段计算即可,在 \([l,i_{max}] 和 [i_{max},r]\) 用不同策略。
然后就是一个贪心判定的过程。第一反应肯定是期限最短的树先种,但是貌似不对,因为这样可能会导致一个期限更长但是链也更长的一个位置无法种到。不过我们不能轻易否决任何一个做法,其实稍加证明这个做法是对的,如果先短后长会超时,我们交换一下二者顺序,发现先长后短也会超时。所以这种做法是正确的。
考场失误:没开 __int128,
if(val1-val2>=a[i]) T=calc(i,dat);
此处二分上界应该是 \(dat\) 而不是 1e9。如果是后者的话,会二分到负的地方去。
T=dat-i+1+a[i]+val2-val1;
一定要想清楚,这里还有 \(-i+1\)
P8272 [USACO22OPEN] Apple Catching G
列出奶牛可以接到苹果的条件,假如一头 \((t,x)\) 的奶牛可以接到 \((t',x')\) 掉落的苹果必须满足 $ \lvert x-x' \rvert \le t'-t$。得到 $ t+x \le t'+x' $ 且 \(t-x \le t'-x'\)。注意有这两个式子后必然满足 \(t \le t'\)。
然后似乎不太好去分配奶牛的去接什么苹果。此时我们不妨大胆地贪心匹配。将约束条件画在二维平面中,发现每个奶牛能接到的范围就是一个倾斜的正方形。斜着不太好看,我们可以先旋转 \(45\) 度,发现越往左下角的正方形包括的区域越大肯定是更优的,于是我们可以贪心将右上角的不优的矩形去先匹配靠右上角的苹果,也就是横纵坐标之和更大的苹果。我们再旋转回来,对应的也就是纵坐标更大的苹果应该被靠上的矩形先匹配到。于是用一个 set 维护即可。
UVA1205 Color a Tree
贪心题。可以先考虑一个错误的贪心,就是最先染色当前可选点中权值最大的点,这显然不对。但是启发了我们,如果当前可选点就是所以未选点中最大的一个,那么我们应该对它进行染色。但是我们无法保证在当前局面下就存在这么一个点,所以我们应该提前操作或者倒序操作,先对权值最大的点进行处理,这个点应该与它的父亲节点操作连续,所以我们可以对他们俩合并,合并后权值如何计算呢,
不妨考虑三个点 \(x,y,z\) 且 \(x\) 和 \(y\) 操作连续。
\(x+2y+3z\) vs \(z+2x+3y\)
作差可得 \(2z-x-y\) , 就是比较 \(z\) 和 $ \frac {x+y}{2} $ 的大小。
于是我们可以给出等效权值的计算方法 \(val'= \frac{x+y}{2}\)
如果是多个节点的等效权值呢,不要想当然认为是 类似 $ \frac{ \frac{x+y}{2} +z} {2}$ 的形式,可以自己手动模拟一下其实是 $ \frac{ \sum c_i}{num}$。 如何理解呢,等效权值没有计算意义,只是为了比大小用的,所以在列式子的时候还是要拆开为每一个单点,不可用等效权值来列上面的不等式!
AGC018C Coins
三元选择显然是不太方便,我们可以先假设全选金币,然后再从金币中选一部分改为银币,还有一部分改为铜币,这是一个二元选择的问题。
我们可以用交换法来确定选择策略,设 \(s_i=b_i-a_i\),\(t_i=c_i-a_i\)。对于 \((s_i,t_i)\) 与 \((s_j,t_j)\),目前 \(i\) 选 \(s\),\(j\) 选 \(t\),考虑何时交换更优。
满足 \(t_i-s_i+s_j-t_j \ge 0\),即 \(s_j-t_j \ge s_i-t_i\) 的时候 \(j\) 选 \(s\),\(i\) 选 \(t\) 更优。于是我们按照 \(s_i-t_i\) 升序排序。所有选 \(s\) 的都在选 \(t\) 的左边。但是注意这里不可选择前 \(y\) 个用 \(s\),后 \(z\) 个用 \(t\),而是应该找到一个分界点,满足在分界点之前中分配 \(s\),分界点之后分配 \(t\)。于是预处理一下前缀前 \(y\) 大 \(s\) 和后缀前 \(z\) 大 \(t\),然后枚举分界点即可。
ZROI2834.念念不忘
全局贪心
全局整体考虑,我们可以转化一下思路,不一定是从子节点往上移动。可以变成从无到有的放置棋子,只需要满足子树总和小于子树大小即可。
我们对于每一个点,将从目前状态放置一枚棋子的代价放入堆中,每次选取代价最小的点放置。同时给上方的链上所有点允许放置的个数集体减 \(1\)。
查群该点如果还能放的话,就算一下下次添加的代价,放入堆中。可以用树链剖分维护,时间复杂度 \(O(n\log^2n)\)。
子树贪心
赛时想到了将目前代价最大的节点往上放最近的可以放的,树剖维护。感觉复杂度要爆,而且难实现,正解很接近,思路有点像。我们不要零散往上放,而是从子树合并上来的时候一起决策放。
如果一个节点放了多个点,为了方便写,可以拆开成多个大代价的点插入好写点。按照上面所说的增减代价放。
复杂度看似极限情况下不对,但实际上是对的。比如我们决策 \(u\),肯定是将 \(u\) 子节点的中权值最大的一些替换为 \(u\) 中最小的一些。将 \(u\) 升序排列,\(v\) 降序排列。假设替换了 \(p\) 次,那么根据等差数列公差 \(u_{p+1}>2u_{p/2}\),\(v_{1,2,..p}<v_{p+1}\),\(u_{p+1}>v_{p+1}\),可得 \(v_{1,2..p}\) 都变成了小于自己一半的数。那么一个数最多也就会变化 \(\log\) 次,故复杂度正确。
ZROI3071.宇宙
定义一点的权值 \(w_u=a_u+dep_u\)。
首先交换法可证我们必然是选择权值最大的点来放,当然我们必须先把它整个子树放完。于是我们可以用 solve(u)
表示放 \(u\) 子树内的所有点。用线段树维护 dfs 序,然后不断找到当前子树内的最大点 \(v\),执行 solve(v)
,然后将 \(v\) 的权值修改为 \(-\infty\),直到 \(u\) 子树内的所有点被放完。时间复杂度 \(O(n\log n)\)。
P2512 [HAOI2008] 糖果传递
先考虑一条线的情况,我们设 \(ave\) 表示平均个数,\(pre\) 代表前缀和数组。
最后答案就是 \(\sum \lvert pre_i-ave\rvert\)。
令 \(s_i=pre_i-ave\),考虑环形是改变了什么其实如果我们在环的一点断开,那么其实就是改变了 \(s\) 数组。假如断开了 \(k-k+1\) 这个位置,那么对于 \(i\in [k+1,n],s_i\to s_i-s_k\),对于 \(i\in[1,k],s_i\to s_i+s_n-s_k\)。又因为 \(s_n=0\),所以对于每个点的变化就是减去了 \(s_k\),那么现在就是最小化 \(\sum\lvert s_i-s_k \rvert\),选取中位数点即可。
道路(road)
有 \(n\) 个点,每个点有权值 \(a_i,b_i\)。从 \(i\) 到 \(j\) 的代价是 \(\max(a_i^2-b_j^2,0)\),求从 \(1\) 出发,经过每个点各一次最后回到 \(1\) 的最小代价。
二分答案加判定是不太好做的。考虑贪心对于 \(a,b\) 排序,大的 \(a\) 匹配大的 \(b\),以此类推。这样子连出来是若干个环,我们要把它合并成一个大环。