贪心

注:该文未整理

必须证明正确性.
证明思路:能将整个问题拆成许多子问题,且所有子问题的最优解之和为最终问题的最优解.
证明方法1,反证法:交换方案中任意两个元素后,答案不会变得更好.
法2,归纳法:边界情况i的最优解可以进一步得到i+1的最优解.

贪心可能是在线的,因此需要合适的数据结构.
反悔贪心:先选了,之后若有更优的则去掉.

例题1. P1080 [NOIP2012 提高组] 国王游戏
先不要考虑向下取整.
用交换相邻元素得出结论,再根据该结论证明交换任意元素都满足.

例题2. P2949 [USACO09OPEN]Work Scheduling G
按照结束时间排好顺序后,假设已经选了前i-1个中的k个(这i-1个可能不能同时选),且为获利最大的方案.
对于当前第i个而言:
如果k<a[i].ed,则这个一定能选.
如果k==a[i].ed(显然,之前的ed<=a[i].ed,所以先前最多选择的个数--k,不可能>a[i].ed),这个能选的条件是之前选的中价值最小的那个,它的价值<a[i].pri,此时替代它的位置.
正确性证明:对于答案序列(假设选择的方法唯一好了),按照这样的方法肯定能被找出.

自选习题1. P1094 [NOIP2007 普及组] 纪念品分组
显然要尽可能多的合并.
每次找最小的,让它去合并能合并中的最大的.
正确性证明:我们需要找到一个变化规律,使得所有其它方式做出的方案,都可以变为这个方式得出的方案.
设小的为O,大的为X,未使用的为_,序号表示同一组(可以设X从右往左为1~k).
先假设一个正解中不是这么合并的:
_O2O1__X2X1如果最小的未被合并,那么肯定可以将O左移.
O3O1O2___X3X2X1如果顺序不对,利用"交换排序"的思想,若O2O1__X2X1合法,必有O1O2__X2X1合法.
现在还有一种情况:O2X2O1X1,此时我们设左边Xi右边的O为Oj,由于Xj+Oj最大,那么必然可以有<Oi,Xj>和<Xi,Oj>.再将Xi和Oj的'X'与'O'换一个位置,就能使得左边为连续的O了.
因此,假如正解比贪心多,那么正解等价转化后的答案可被贪心构造出来,此时就矛盾了.所以,贪心即为正解.

自选习题2. P4447 [AHOI2018初中组]分组
每次考虑所有为i的人,与它相关的是i-1的情况.
先是边界,i最小时每个人作为一个队列的头.
每个i结束后,队列的个数就是==i的a的个数.
假如之前有2个队列,现在有4个数,那么原本两个长度都++,新增两个队列.
假如之前有4个队列,现在只有2个数,那么肯定是加在短的队列后,因为假设长度为{4,3,2,2}你若加在长的后,答案就不会大于2了.你这时肯定会删去4-2=2个队列,将ans与这2个长度取min,如果删去{4,2},留下的3无论怎么加都不会影响ans,还不如把将要连在3后的内容贡献给删去{4,3}时的{2,2}.

别人的文章1:https://www.luogu.com.cn/blog/83547/tan-xin-jiang-xie
例题1. P1016 [NOIP1999 提高组] 旅行家的预算
反悔贪心(思路来自id20375):
1.在起点加满油.
2.到第i个加油站把油箱里价格>P[i]的油退了,换成价格为P[i]的油.
3.每次烧油就找最便宜的油烧.
计算答案只需在烧油时即可.

例题2. 国王游戏(上有)

习题1. P2512 [HAOI2008]糖果传递
随便造一组例子,然后将每个数减去平均数,如+4 -2 +1 -3 -2 +3 -1.
假设1给了2<x>个(x为负数则表示2给了1),那么可以依次推出2给了3<x-2>个,...,此时答案就是这些数的绝对值相加.
将这些排序后变成:x+(-6,-4,-4,-3,-2,-1,0),取中点,x为3的时候这些绝对值相加最小.(可用数轴,即绝对值的几何意义理解)

例题3. 喷水装置 (应该是YBT上的)
题目:长L米,宽W米的草坪里装有n个浇灌喷头,每个草坪都装在草坪的中心线上(离两边各W/2米).我们知道每个喷头离草坪中心线左端的距离,以及它的浇灌范围(是一个正圆,给出半径),问最少几个喷头能够同时浇灌整块草坪.
经典区间覆盖问题,将左端点排序后,一开始的能选集合为所有L<=0线段,这些线段中选择R最大的即可.(显然每一条线段只会被比较一次)

例题4. P1717 钓鱼
题目:小明有H(1<=H<=16)个小时钓鱼,假设有N(2<=n<=25)个鱼塘都在一条水平路边,从左边到右编号为1,2,3...n,小明希望用这些时间钓到尽量多的鱼.他从湖1出发,向右走,有选择的在一些湖边停留一定的时间钓鱼,最后在某一个湖边结束钓鱼.他测出从第I个湖到i+1个湖需要走5*ti分钟的路,还测出在第I个湖边停留,第一个5分钟可以钓到鱼fi,以后再每钓5分钟鱼,鱼量减少di.为了简化问题,他假定没有其他人钓鱼,也不会有其他因素影响他钓到期望数量的鱼.请编程求出能钓最多鱼的数量.
显然不会走回头路,则先枚举走几个湖,再贪心这些湖中的鱼(排序后选最大的那些,显然合法).
trick 对于不确定的值,先采用枚举,再贪心求最优解.

习题2. P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
证明部分源自见 @学委(49474)
1.最优方案可以表示成一个二叉树,总代价=每个点权*点深度,表示这堆果子被合并的次数.
注意:果子在叶子节点.
2.最小的两堆一定在最优方案树的最深层,否则交换后答案更小.
3.同层交换不影响答案.
4.因此第一步唯一,合并后回到1.

END.

别人的文章2: https://djy-juruo.blog.luogu.org/qian-tan-fan-hui-tan-xin
反悔贪心的思想是:既然这次不一定是最优,那么就先放着,若以后找到更优的再取消这次操作,并选取更优的操作.
这样的话只要保证当前最优即可,因为以后的更优(即选取前i个时的最优解)可以由反悔得到.
例题1. P5662 [CSP-J2019] 纪念品
部分分(物品数=1时)反悔贪心做法:若明天价格高于今天,则今天全部买入且明天时卖出换成钱.
先换成钱,再判断是否买入.

例题2. CF865D Buy Low Sell High
分析题目的基本单元--<第i天买入,第j天卖出>.
你只需要保证每天答案均最优.
现在有i-1天时的最优解,为了便于观察,将它们放到直角坐标系中,则每一个选择对应了一条左下-右上的线段W,而未被选择的股票视为一个个点.
你的策略是将当前值和可选集合比较--可选集合为线的右上端的点与未选点比较,找到其中最小值x,若x<now,则改变连接方式:若x此前连上了y,则free(x)(将x变为未选点);否则连接x-now.
假设最优解T比它还优,首先最优解必定选now,不然就是now-1时的最优解了,而你所做的选择(记为U)必然使得ans至少+1.
然后设最优解T中now与y连接:
1.y在你所做的解中为未选点,T<=yourans.
2.y在你所做的解中为左下点,y右上的x在此时被你free掉了,若它在T中不匹配,则T就是yourans.
若它在T中存在匹配,则一路找下去,一种情况是结尾z在T中,另一种即在U中.
在T中:则你的now可以去选择匹配z,此时与T的"右上点"和"左下点"是同样的.
在U中:则你的now也还可以去匹配z,即相当于释放z了.
3.y在你所做的解中为右上点,那么它左下的x按照类似的方法可以得出:都是U的可选集合.
论证思路有些像二分图匹配...
另外,关于为什么now连上某个点时它要被push两次:第一次被取出时为断掉它的联系,它就变成了"自由点",还可以被再加入.

例题3. P2949 [USACO09OPEN]Work Scheduling G
前面有.

例题4. P4053 [JSOI2007]建筑抢修
按照毁坏的时间从小到大排序,记录之前修好的所有内容所花时间{T},剩余时间sheng,设当前修复所需t时间.
假如时间够用就修,此时可以将之前的时间看成一个个方块,往前推一段距离直至刚好塞下这个时间块t.所以说这是可行的.
假如时间不够了,看看之前的时间块中有没有>t的,若有则将其取出,然后塞上这个.
不不不,我重新换个思路:
证明一个块被踢出去后就不可能再回来.
他被踢,必满足:枚举到他结束时间前不存在>他的块,且剩余空间不够一个小于它的块放进去了.
所以他要是想加回来必然会挤出至少一个块,且剩余空间会因此更小.
那么在这些已经"等效"的块中选取最大的踢掉肯定没错,因为换成别的会更劣.

例题5. P1484 种树
很显然,就算之前把树都种满也没事,每次只要把之前价值最小的拔过来种在现在这个坑里即可.
来自 @Celtic(176990):
考虑到如果Ax最大,我们如果选了x-1,那么一定会选x+1,不然选别的一定不如选x和另一个.
所以此时我们可以选择Ax,把它从堆中取出,在同样的位置放入A{x-1}+A{x+1}-Ax,然后把A{x-1}和A{x+1}删掉.
这时如果我们以后选择新加入的这个点就相当于选择了A{x-1}和A{x+1},效果是一样的
注意边界:边界一旦被选则直接删去.
但是为什么会想到这个思路呢?

例题6. CF436E Cardboard Box
正解很骚啊:按照b升序后,假设标准答案选择2星通关中最大的为第k个,则前k-1个必然选>=1星--不然你把这个时间花在前面这个不选的关卡上更好.那么>k的最多只选1*;<=k的最多再选1*,找最小的就行了.


做一些CF上的贪心题:
CF3A Shortest path of the king (1000*)
显然求两点曼哈顿距离即可.

CF16B Burglar and Matches (900*)
显然贪心的先拿火柴最多的盒即可,即按照b降序处理.
用pair更方便.

CF34B Sale (900*)
适用于初学者学习排序的思想.

CF50A Domino piling (800*)
适合入门,n*m/2即可.

CF58A Chat room (1000*)
适合字符串入门,从前到后去找每一个字符即可.

CF90A Cableway (1000*)
只是细节多了些,适合入门难度的进阶.

CF137B Permutation (1000*)
重复的数字必然被改掉,发现可以按顺序改成所有没出现过的数,因此答案即为n-出现的不同数字的个数.

CF1622B Berland Music (1000*)
用冒泡的思想证明贪心正确性,即临项交换不会更劣,则必换.因为你构造的答案能被所有可能是答案的答案,通过不会变得更差的交换得出,则你所构造的即为最小答案.

CF1659A Red Versus Blue (1000*)
显然要让R均匀分布在每个B之间,因为b<r,所以就是一个抽屉原理.

CF1620B Triangles on a Rectangle (1000*)
仅需考虑极端的情况并将其与其它情况进行比较以缩小答案集合.

CF1487C Minimum Ties (1500*)
应该舍弃先前的凑答案的方法,用代数方法得到最优解,再用信奥思维去尝试构造.
比如这题就可以严格用代数方法算出最优解.

CF1490F Equalize the Array (1500*)
枚举剩余多少时,为了方便得到答案,要将数据进行排序及前缀和处理.

CF1492C Maximum width (1500*)
显然只是单纯的找出最大值,因此需要得到m中每个字母在n中的位置最值(最左最右能到哪里),然后相邻字母找最大差值即可.

CF1499C Minimum Grid Path (1500*)
显然要将向上走和向右走给分成两部分思考.然后再让花费最小的走的最多,其它均走一步即可.
不过要注意的是,可以提前走完,因此在i>=2时每次更新答案即可,仅需记录当前最小值和前缀和.

CF1515D Phoenix and Socks (1500*)
小技巧:swap可以直接交换数组.
或许贪心证明不必太严谨:先去掉配好对的袜子.设左袜子数>=右,且某一种颜色中有左袜子,那么不妨直接将其变成右袜子(且仍需保证L>=R),这样只需要一次配对.最后重新着色所有左袜子.

CF1547C Pair Programming (1100*)
显然k越大越好.
假如现在b序列的首个位置将不合法,那么就不断选a,直到a为空或也不合法.

CF1516B AGAGA XOOORRR (1500*)
考虑答案的可能情况:三个相同或是两个相同的数,不然更多相同的数仍可以异或成三个或是两个.
然后就是n^2搞一下就行了.
当然还有更快的方法:假如答案为2个,那么全部xor一下为0.
否则若可行,答案必然为3个,此时整体的xor结果为S,那么只要找到一个S就清0再接着找,肯定能在正解的位置(甚至它之前)找到第二个S,然后剩下的必然也为S.复杂度为O(n)

CF1526C1 Potions (Easy Version) (1500*)
选择一些数=在原序列中删去一些数,使得前缀和非负.
原序列的前缀和有的地方为负数,从前往后看,对于任意一个负数的位置,不断删去它前面未被删去的最小的负数,直到这个位置非负(且之后的前缀和都要更新,即减去这些负数).

CF1551C Interesting Story (1500*)
显然要枚举每个字母时的答案,对于'a',每个字符串就被抽象成了一个数x,x=该字符串中'a'的个数-不是'a'的个数,然后降序找前几个即可.

CF1552B Running for Gold (1500*)
题目看懂了就很好想了,显然若x战胜了y那么y一定不会是金牌.
那么用打擂台的思想先得到可能是金牌的选手,再让他跟其他所有选手都比一场检验一下即可.

CF1553D Backspace (1500*)
当s和t奇偶性不同时,s的第1个字符必删,因为肯定存在一个字符作为BS时前面无内容--要么它就是第1个,要么第1个已经被删掉了.
然后让两个字符串0101报数,发现0只能和0对上,1同理.
那么第一个数当然是配对最前面的为0且字母相同的更好,这样相较于它配对后面的情况,会为下一个数留下更多的可选空间.

CF1579C Ticks (1500*)
自下而上找每一个要被涂色的格子(因为它特别),找出它最大的k,若可行则涂,若不行,此时再看看这个格子有没有在先前被覆盖过,若无则"无法做到",否则没事.这样对于答案的涂法你肯定也能涂,只是可能重叠的会多一些.
当然,先全枚举一遍也是可行的,只是要全部涂完才统计答案而已.
当格子较大时可以斜着划分方格(类似八皇后),记录每一个斜线上还能延伸多远,这样时间复杂度只是O(nm).

CF1621B Integers Shop (1500*)
先显而易见的是能确定有哪些s包含了最左边的数和最右边的数.则只需要在这两类中选择价值最小的加起来即可,要注意的是可能存在选择一个就能全部满足的情况.

CF1659C Line Empire (1500*)
假设首都最终迁都到k,那么攻打1~k之前首都必然先迁移,之后的就是二次前缀和的事情了.

CF1638D Big Brush (2000*)
考虑反推:对于最后一次,若某块位置能被涂色,那么这个块必然是2*2相同的颜色.那么撤销后就变成了'0';
对于接下来的步骤,假设当前格子为(i,j),在不越界的情况下,若以它为中心的3*3格子里某一个2*2的块只含它的颜色或是0,那么就是可以涂的,并将这块都变成0.
至于如何枚举--每涂完一个2*2后都将它外面的4*4的部分加入队列(已在的or已为0的就不用了),因为这些是受到影响的.

CF1632D New Year Concert (2000*)
将f的要求分层:f(前i个)=f(前i-1个)+f(第i个).所以先只需考虑第i个对应的要求.
将"不等于"左右两部分视为两个函数,特征是:当l不断减小时gcd不断减小,而r-l+1不断增大,因此最多仅1个交点.
如何改变?gcd与数论有关,那么考虑"质数",于是显而易见的,将某个数改为特大质数后gcd一定就满足=1了,即消去了交点.而为了后面考虑,这个变为质数的数要尽可能靠近末端,使得后面的当与它进行gcd后即可不再担心l往左的事情了.
问题就来到了如何找到这个点,显然差是严格单调的,那么二分一下就行了,对于gcd用线段树维护(查找时log步到位).
当然st表更不错(st[LogN][N]哈),因为你可以记录"上次修改的质数位置",当[l,i]包含它了就特判一下.

CF1650E Rescheduling the Exam (1900*)
蛮水的,找到最小的间隔(若不止一个显然直接返回它-1),else try to move its Left and Right.

CF1657D For Gamers. By Gamers. (2000*)
一开始得到的是不等式,化简,记atk*hp=power.
发现C<=1e6,思路是预处理出每个C最大的power,然后前缀取max,即可得到每块钱能雇佣的power,每次二分查找即可.
问题在于如何求每个C的power:首先我们将一开始的<power,cost>存入C,然后考虑倍数--C=1时,更新所有1的k倍数的钱所能买到的power为C[1]*k(前提c[1]!=0),C=2时更新2的倍数...若你想顺带把质数筛一下,那就错了,因为可能是一个兵种很强,但是cost=6.因此老老实实枚举即可.调和级数累加为O(ClogC)的复杂度.

CF1659D Reverse Sort Sum (1900*)
去看看C1,Cn这种特殊位置的规律,发现由C的总和可以得出最后一行最后是几个0和1,然后与Cn比较下就得出了An.再将右边和下面削掉,由于是连续的1,因此可用线段树维护.

CF1661D Progressions Covering (1900*)
利用上题思路,看看Bn,答案就自己蹦出来了:在n-k+1位执行ceil(Bn/k)次累加.
同理,Bn-1也是类似的,不过由于累加的是等差数列,因此线段树维护的方法为:记录首项,公差,push_down时将这个等差数列拆开.add时也是如此.

CF1672F1 Array Shuffling (2000*)
先由于b的交换与位置无关,所以本题与位置关系不大.
去思考:假设已构造出b,答案的策略会是什么.
设每个交换就是一条线,这些线连成了许多连通块,每个块内进行size-1次交换必可达成,此时答案=n-块_cnt.
手膜一下发现每块内不会有重复的数字,否则可以分成两块,因此块的最小值必>=max_cnt.
再构造一下方案,只要最多的数字所在位置填上次多的,次多的填上第三多的,...即可.

CF1624G MinOr Tree (1900*)
与位运算相关的按位考虑,假如答案是10101,那么枚举到"1_ _ _ _"时应该是"11111"合法而"1111"不合法(而不是"10000"的合不合法),然后再考虑"10111"是否合法,若不合法则撤回.
一开始排一下序,然后加边时只需考虑到<="11111"即可.(虽然复杂度还是O(64M+MlogM))

CF1620D Exact Change (2000*)
额,1元币最多1个,2元最多2个,剩下都是3元.
感觉没啥意思.

CF1619G Unusual Minesweeper (2000*)
互相能引爆的地雷看作一个连通块,自然爆炸所需时间即其中最短时间.然后从时间久的开始点爆即可.

2022/5/22:
CF1677C Tokitsukaze and Two Colorful Tapes (1900*)
先不难想到去掉相同颜色(对答案无贡献)的块,并将剩下的块看成环.
然后将环对应到图中!相同的点给它缩起来,则问题变成:给每个点一个值,使得每条边边权(点权之差的绝对值)和最大.
如果环长为偶数则考虑间隔黑白染色,这样对于某几个给定的数,大的一半填在黑,小的填在白,答案为(较大一部分的和-较小部分的和)*2.
如果环长为奇数(2n+1),最终填的结果,若当前点权大于旁边两个,记为H(黑),小于两个记为B(白),否则记为X(随便起的名字),贡献则为2H+X(H,X要代入点权哈),发现当存在连着的多个X时,必为H>X1>X2>X3>B,此时能将这些X通过交换变的只剩下一个,这就启发我们:能否构造n个H和B,1个X解决问题,且有任意的H>X>B,发现是可行的,只要染色时最后一个染为X即可.
那么这许多块中,让H为最大那些,X为去掉H后的最大那些即可.

CF1675F Vlad and Unfinished Business (1800*)
显然将树砍掉必不要的边后思考一下即可.

CF1673F Anti-Theft Road Planning (NOT) (2400*)
Hint1:主要目标是给所有建筑物分配从0到1023的数字A(i,j),使所有建筑物得到不同的数字,并将建筑物B(x1,y1)和B(x2,y2)之间的道路长度分配为A(x1,y1)^A(x2,y2).在所有这样的分配中,尝试找出道路长度之和最小的一个.
BY(CF:willy108):对于行(i,j)->(i,j+1),j不变时所有的值都应该是一样的,这样你就可以知道是否通过j->j+1这一行.
还是有些不理解,之后补补格雷码.

CF1674E Breaking the Wall (2000*)
显然考虑这两个数的位置关系:相邻,间隔1个,间隔大于1个.
间隔大于1个:直接找序列中最小两个数x,ans=(x1+1)/2+(x2+1)/2
间隔等于1个:设为(x,o,y)注意到无论怎样答案都不小于(x+y+1)/2,因为无论怎么点,(x+y)每次都只减2,构造的方法为:点中间那个直到x或y为0,再点剩下那个.
相邻:先点大的,将两个点到相同后(或一个为0,这样则直接继续点大的),此时计算(和+2)/3即为最小次数.

CF1672E notepad.exe (2200*)
可从交互次数的特征中找答案:n+30的30意味着要二分,二分自然是确定L的长度.然后考虑什么情况下能更新答案:假如真正的答案分成了k行,那么它的长度必然是floor((L-1)/k),这是因为结尾的k-1个空格使得每行长度均少了1.

CF1650F Vitaly and Advanced Useless Algorithms (2200*)
有些"包容"的感觉,遵循"哪门作业先交就先写哪门"的原则--为何?
因为标准答案对于作业方案的安排中,必然可以将最早要交的作业所使用的时间片段挪到最前.而你经过01背包考虑后的结果必然花费最短时间.

CF1641C Anonymity Is Important (2200*)
首先一个区间内有多少人肯定没病,这可以线段树维护.
那么对于一个单点询问i,若没病则查询sum即可得出.若它不在"由没病信息得出的正常人"中,那么可以向左和向右找到最大区间[L,R]使得这个区间只有它"不知",别的都"没病".然后找找是否存在"有病区间"跨过了它即可.
这时显然有病区间的左边界要在[L,i]内,且此时右边界也要在[i,R]内.
关于如何维护这件事:(Lg,UID=357545)说,把其放入线段树,查询区间最小即可,加入时只需单点取个min.COOL.

CF1635E Cars (2200*)
(Lg,UID=212488):有关系的车的朝向都是不一样的,这个可以用二分图染色染一下--出现奇环则不行.(类似于带权并查集!)
然后是相对位置,将第一对某一个车的初始方向视为向左,那么另一方则向右.如果可行,那么每一对中的右->左都连一条边,会是一个DAG,此时随便跑出来的一个序即为车的排列顺序.

CF1630C Paint the Middle (2200*)
显然可以先分成许多互不相包含的区间,之后没啥思路了.还是按照最小区间覆盖等想吧.

CF1626D Martial Arts Tournament (2100*)
每组的人数必须是2的幂,这提供了思路:直接枚举每一组有多少人.
假如前两组需要8+4人,现在有{2,4,3,5(超了)},那么它应该要选{2,4;3},而不会将最后的一个或一些数(x)让给第3组.因为这会使你给前二组填数的成本+x,而且万一这最后一组+x后超过原先的2的幂,那么更亏;同样的,第一组也会优先满足自己的需要,很自然想到利用前缀和+二分维护找数的过程.

CF1622E Math Test (2200*)
n=10说明二进制枚举,枚举的自然是每个人超出还是低于(等于)期望.
然后若超出期望,则题目贡献1权重,减去期望;否则贡献-1权重,加上期望.
最后大的分数给权重大的即可.

CF1621D The Winter Hike (2100*)
震惊了,竟然只要在八个点中取最小值即可...还是要多想想特殊点.

CF1619F Let's Play the Hat? (2000*)
显然只要循环的将人排到小桌子上即可.
配不上评分.

CF1618G Trader Problem (2200*)
将"可互相交换"的两物品连一个无向边,当k不断增大时,这些会形成一颗树(类似并查集),在每个并查集中,原有几个选择,现在就选出几个最大的即可.
为了使得代码能够将其表达,排序并邻项作差,并在差值<=2e5时记录,建立前缀和以得到新值,在每个点建一个sum以减去原值.

CF1616E Lexicographically Small Enough (2200*)
先判断无解,接着去思考答案的特征--第一个小于ti的si的位置在哪?
答案肯定分为两段--相同的前缀和第一个不同的字母,为了构造相同的前缀,则对应t前缀中的字母,从前往后找s中与之相同的并挪到最前,然后第一个不同则找此时剩下的s中小于ti且最近的即可.
维护方法:对于每个字母Ai,我们将其进行"懒惰标记"--当i后有Aj移到了Ak(k<i<j)时,将原本[k,j-1]均+1,要注意的是,此时有可能已经移走了该区间内的一些字母,不过没关系,反正取下一个令前缀相等的字母时,不会再找这些已被移走的位置了(用vector存字母的位置).
区间加自然还是线段树欢乐.
对于Aj会移到哪个位置,其实直接移到开头即可,因为之前的一些字母已经被用过了,移动是相对的.

CF1616D Keep the Average High
发现是与平均数相关,要能想到全体减去x与0比较.
问题变成:使得所有"部分被选择的a构成的长度>1的串,和>=0".
现在要找到约束,可以先假设某个方案不满足条件,再看看能否细分为一个更小的不满足条件的方案,发现只要长度为2,3的子串均>=0即可(注意,仅是长为2不行,比如{5,-4,5,-4}),因为所有更长的串均可拆成许多2和3串的和.
贪心思路为:若前一个未选,当前必选;否则算下与前面的和,若可行则选.
验证贪心的正确性:(O表示选择,X表示不选)
贪心结果:OOXO?
若答案为:OXOO? 变化的是第2个,此时的?必然不优.
贪心:OXO 此时变化第1个
答案:XOO 分析同上.
贪心:OOX
答案:XOO
此时第一个数必为负(否则答案不是这样),第二个为正,第三个为负(否则贪心可选3个).那么第4个假设可选(否则就"隔开"了),且其必正,而第5个呢?贪心的情况中不用考虑3+4+5,但是答案就要考虑了,且3为负,则选5的可能性答案还是小于贪心.
由此贪心正确性得证.

CF1612E Messages (2000*)
先发现k<=20,而期望在t==k时发生突变,因此分类讨论:
当t>20时,每个人的期望即(0 or 1)*ki/t,那个0 or 1取决于是否选中了它的消息.
显然若一个消息是许多人同时所需的,它的价值即为sigma{k}/t,直接将每个消息具备的k降序即可.
当t<=20时,一部分人的期望同上,另一部分为 0 or 1.那么还是同理,只是要用double存放每条消息所贡献的期望了.
--能贪心是因为各消息的期望彼此独立.

2022/5/29:
P1650 田忌赛马
这题是用贪心的思想思考,用区间DP实现.
by(LGUID=55918):"田忌一定是将他马按速度排序之后,从两头取马去和齐王的马比赛"
先都降序排序.当田忌当前马A>齐王当前马a,由于A肯定要在剩下的所有马中选择一个,那么选a是严格不劣的.
如果A<a,那么田忌为了保证更多的"有生力量",派出最小的即可.
当相等时,先放着,比较最慢马B与b:
若B>b则先让它们比掉,也是严格不劣.
若B<b则B一定不能带来收益(将+200和+0视作收益+2和+1),那么让它跟a比,反正它都会输.
B=b,此时若(1)A--a+B--b,收益是2,但若(2)B--a则A最劣的情况下仍然可以选取b,收益还是0+2=2.注意,刚刚提到了"最劣的情况",这是指(1)中的配对方法除了A和B,别的被(2)完全采用,此时收益一样,那么(2)此时敌方的阵营更弱了,所以果断舍弃(1).
记得当B--a时若相同则收益+1!
启示:比较两端.

CF545C Woodcutters (1500*)
先砍倒两端的树,若第二颗树能往左倒,那么这对之后无影响,必然是可行的.若只能往右倒,假设它使得原本能往左倒的树i不可了,若i能向右,再看看对i+1的影响...
最后一定会停在两种情况之一:(1)当k-1向右时树k能向左倒,那么自然是极好的.(2)就自然是k不能向右倒(注意哈,若可以向右倒那么还不算停止),此时从2~k共k-1棵树,倒了k-2棵<=>留下1棵,显然就算第2棵不倒(因为它无法往左)这些树最多还是只能倒下k-2棵.而且这两种情况对后来的影响是相同的,因为并未占用后来那颗树往左倒的空间.
而且这两种完全等价,因为(2)中第2棵若是不倒,之后的树一定能达成倒下k-2棵的结果,只要做出与(1)相同的选择即可.
但是由于这两种情况(1)不会比(2)更好(均是必留1棵),所以选择哪个都一样,为了贪心的方便,选择(2).

CF482A Diverse Permutation (1200*)
思路蛮巧妙的,比如k=5只要在开头放上1,n,2,n-1,3,之后4~n-2即可.
怎么感觉有些像阻尼振动呢...
启示:打表找规律.

CF425A Sereja and Swaps (1500*)
直接枚举最终选择的区间端点,然后将外面的最大值和内部的最小值替换(要先比一下是否更优).
启示:n<=200这种考虑N^3等算法,即枚举区间.

CF525D Arthur and Walls (2400*)
(题解区:)可以去考虑最小单元--2*2的图形若有3个'.'则必然要改剩下一个'*'变为'.',这是必然的,因为所有符合要求的答案中都不能出现这个.那么BFS拓展即可.

CF1175D Array Splitting (1900*)
分析答案的性质--若用条形图将每个数选择的次数表示出来,会发现是一个单调不降的图,而且可以被横着划分成若干段,且每段都以n结尾.
也就是说,题目等价于取k个后缀和,则找最大的那些即可.

CF1203F1 Complete the Projects (easy version) (2100*)
CF1203F2 Complete the Projects (hard version) (2300*)
正常人都知道先完成所有升Rating的,显然按照"需要的Rating"升序排序即可.
然后就是降Rating的,发现本题全等于"安排计划"--每个计划有一个截止时间,完成的价值是1.这不就相当于每秒钟掉1个Rating,进行连续的bi秒能完成第i个计划吗.注意下最终Rating不能<0.
截止时间应为max{ai-bi,0}.可以思考下为什么.

CF1176C Lose it! (1300*)
这不就视为六个未完成的序列吗,每读入一个数就判断是否能使得一个子序列末尾接上它以构成下一个序列,最终保留的即为含6元素的序列.

CF1176A Divide it! (800*)
显然不断除以2,3,5即可.

CF1200B Block Adventure (1200*)
模拟一下,跳走前拿走这一列的砖块.

CF1202A You Are Given Two Binary Strings... (1100*)
先发现y末尾几位的0无法对x的末尾造成影响,也就是倒过来x那末尾几位不会变.则使得y末尾的1和x从能被影响到的最后一个1对齐即可.

CF1181B Split a Number (1500*)
如果没有0则中间分段.那么0既然不能作为开头就将原本在中间的指针左移和右移分别得到两个值,比较一下即可.

AT4894 [ABC136C] Build Stairs
倒序考虑,显然最后一个必-1,倒数第二个不-1的原因只可能是现在的它与-1后的后面那个数一样了.

CF1185C2 Exam in BerSU (hard version) (1700*)
或许可用权值线段树维护.嗯,就是可以.
每个人计算M-ti后剩余的时间,再将这些时间分配给用时最少的人.
那么可以按照t先排序,用普通线段树维护即可(当前节点的L,R为在[L,R]中的人的信息:总用时,人数),然后单点修改即可.

CF1185B Email from Polycarp (1200*)
(LGUID=361726):把一段重复的字符串化成一个字母x(表示重复的字母是什么)和一个数字y(表示重复了多少次).对两个字符串均如此处理,若最终所化结果长度不同或是y1>y2了,那么就是不合理的.

CF1180B Nick and Array (1500*)
操作可逆,故先都变非负数.
优先变小的,因为增长的比例大.(0也适用)
n为奇数时最后剩下1个不能变,偶数时全变.

CF1186D Vus the Cossack and Numbers (1500*)
先都下取整,再微调即可.
微调即随便加1直至和满足结果.

CF1197B Pillars (1000*)
就是说一个柱子上若有2个盘子它就不能动了呗.
那么肯定移到n所在的盘子,双指针向两旁扩展寻找下一个即可.

SPOJ DIVSTR - Divisible Strings https://www.spoj.com/problems/DIVSTR/
等价于找到剩下的字母的最大数量,则考虑没删的怎么找出来,按顺序匹配下去就行了.

CF916B Jamie and Binary Sequence (changed after round) (2000*)
先得到其二进制表示,check一下k是否够用.
然后不断把所有最大数k倍增为两份k-1直至无法整体加倍.此时再考虑字典序最大--逮着最小的那个不断让它裂开,取裂开后的其一,再裂开,如此往复直至k用完.
启示:FIRST & LAST

CF913C Party Lemonade (1600*)
先修改价格,可以使得每种果汁至多只买一瓶.
再二进制拆分即可得到恰为L的价格,然后不断lowbit一下.

CF145B Lucky Number 2 (1800*)
显然只要构造出47和74且使用的4和7最少,再在7的旁边插入7,4的旁边插入4即可.
4开头7结尾:47比74多1个;4开头4结尾:一样多;7开头4结尾:74比47多1个;7开头7结尾:一样多.
当要求的47和74个数相差1时,"原始方案"唯一,当47==74时,哪个数字提供的多就放外头.

CF145A Lucky Conversion (1200*)
显然能换则换,剩下一种后全改掉即可.

CF138B Digits Permutations (1900*)
毫无疑问的,先统计每个数字出现的次数.最后一位需要和为10,再往前需要和为9.
那么只需要枚举10是怎么来的即可.

CF125D Two progressions (2200*)
(LGUID=123298):取出前3个数,由容斥,必有两个数在同一个等差数列中--比如第1个和第2个在同一等差数列中,再分离出该等差数列,检验剩下的是否亦为等差数列即可.

CF898D Alarm Clock (1600*)
类似滑动窗口的移动区间(当然不是说这题要用到这个),当你想掐死一段区间的闹钟时,优先掐后面的,因为还要满足下一个区间[L+1,R+1],[L+2,R+2]...的利益最大化.

CF118C Fancy Number (1900*)
对于每一个0~9都尝试一遍,假如现在是8,有一些7和9,为使得字典序最小,优先改靠前的9为8,再改靠后的7为8.因此得出结论:先改大的,再改小的(当然得在绝对值相同的情况下).

CF893D Credit Card (1900*)
这里的"金额不能>d"好像是仅银行的操作完成后会检验一次.
先分段,按照0划分,每段提取出两个信息:a.该段银行给你的累计金额;b.累积过程中与d的差距.比如(-6,+4)表示该段银行共扣除你6元,你在之前段结束后剩余资产最多4元.显然b<0则无解,否则你一定可在最后一天造成充个6元.最后一段由于末尾无0,只需检验b即可.
接下来是充钱的时间,肯定只在每段的结尾,也就是在0时,能充就充,之后过量了则穿越回来少充一些:比如d=10,你在某个0处充到了10,接下来有(-3,6),则最多进入6的资产,所以少充4元10-4=6,在这个段的0处金额为6-3=3>=0,无须再跑一趟,接下来(-3,1),先将剩下的资产与1取min,发现-3后<0,则这个0天必须充.
当出现a>0时,这些钱要单独算,因为你就算一点不充它也会作为后一段的资产,所以当其大于后一段的b时肯定会被查.
所以钱分为 你人工充的 + 银行给的.

CF76B Mice (2100*)
先处理出题目中必然发生的信息:有的老鼠A的目标唯一,这也导致有的奶酪有个时间,时间一到就被吃完.
对于原有双向选择的老鼠B,现在其实有的选择会使它吃不到(但是它不知道),因为这个奶酪被只有唯一选择的老鼠吃掉了,则删去这些选择.
有一些奶酪可被两只B同时达到,则必选,这样可以把其它奶酪让出.那么剩下的匹配就是你死我活的局面了,将B和它能到的奶酪连无向边,每个连通集的min{奶酪数,老鼠数}即为能吃饱的老鼠数.

CF73B Need For Brake (2000*)
将>m的排名的得分设为0.
二分名次,假如10个人排第7,若能到第3<=>他加最高的分且4,5,6名倒序加分(即第4名加上最后一名的得分,这个得分是指在补0后的,每个人都有的得分)后排在他后面.
最低也是类似的做法.

CF883K Road Widening (1800*)
只需要先都变成路,再转变一部分为草坪,然后判断下路是否缩小了即可.
答案的"相邻路宽度不能差超过1"这个性质应由现在最窄的路去向两边扩展,即为两边界定一个上界.这可以通过正着+反着各扫一遍更新得到.

CF49D Game (1800*)
最终的答案只有两种,开头分别为0和1.
跟原来的字符串不相同的个数即为操作次数,随便画几个发现总能达到最小操作次数.

CF58C Trees (1800*)
启示:"连续递增"则思考减掉一个公差为1的等差数列后差值相等.
理由是对于每一个答案序列,都包含了一些该序列中的数,找出包含最多数的答案序列即为要改成的序列,然后这些数通过什么途径能被证明在同一组--减去等差序列后差相等.


2022/7/7: -- 应追求优美的证明.
P1208 [USACO1.3]混合牛奶 Mixing Milk (普及-)
<特征>可以拆开来购买,因此就是许多价值为1,价格不等的物品.

P4995 跳跳!(普及/提高-)
只考虑最小和最大--记作h[1],h[n].
对于你的选择 h[1]--h[n] + h[s]--h[t] (h已由小到大排序,1<s<t<n)
和答案的选择 h[1]--h[t] + h[s]--h[n]
记h[n]-h[1]=A,h[t]-h[s]=B,发现A+B为定值记为C;答案的两个差为A'和B',A'+B'=C.
那么A^2+B^2=C^2-2AB,使得AB尽可能小.
由于"和一定,差小积大",则使得A,B差值最大即可.肯定有|A-B|>|A'-B'|,则此时答案可以改成你的选择且更优,则答案不可能是那种选择,则你的选择即为答案.
现在确保了h[1]--h[n],然后天翻地覆,h[n]即为地,即刚刚的h[1],再同理得出h[n]应该匹配h[2],...
<特征>先保证获得最大价值(本题为h[n]-h[1])肯定不劣(本题即任何情况都可以通过不劣的转换得到该对),然后问题可以缩小1,进行"递归"似的计算求解即可.

P1094 [NOIP2007 普及组] 纪念品分组 (普及-)
<特征>枚举的开端随意(从小到大或~)但一定要有方向,也可与答案进行比较.


2022/7/8
P1199 [NOIP2010 普及组] 三国游戏 (普及/提高-)
将默契值从大到小排序,比如是a--b,c--d,a--e...这时想必答案呼之即出了--第一轮选择a,第二轮任意选,第三轮选择e,此时电脑必然抢不了a.
假如a--b,c--d,a--c这种,也是可以的.
而且两个武将均第一次出现时,这个配对不可能被达成.
<特征>武将有国界,而默契仅1个.故尝试从默契值着手.

P2672 [NOIP2015 普及组] 推销员 (提高+/省选-)
选择4家推销时,答案的来源为:前三家必然选择a最大的,第四家(1)可以再选择a最大的,然后答案加上这四家的最远距离;(2)选择剩下a+2s最大的,这时四家的最远距离再重新计算一下.这样别的选择都必不优于二者之一.
由于要计算a的和,那么按照a大到小排序,同时记录前i个中最大的s即可.
<特征>距离s是特殊的,只会计算最大的,那么它是一个贡献点;除了它外还有a.考虑答案如何由这两个贡献点组合.

P1080 [NOIP2012 提高组] 国王游戏 (普及+/提高)
当证明相邻两项满足某个内容(这个内容必须只与自己相关)后能使得答案不劣,那么可以用其推出快排的合法性.
本题可以证明相邻两项在不向下取整时,若满足a*b小的排前面使得结果不劣.
而向下取整不改变两人得到的钱的相对位置--若A<B,此时最多只是A<=B,即仍然不劣.
<特征>邻项交换对前后无影响.

P2123 皇后游戏 (省选/NOI-)
先证明若任意两个i<j,j<k都满足min(ai,bj)<=min(aj,bi)(j,k类似~),那么i,k不一定满足:
for(int a1=1;a1<=6;a1++)
for(int a2=1;a2<=6;a2++)
for(int a3=1;a3<=6;a3++)
for(int b1=1;b1<=6;b1++)
for(int b2=1;b2<=6;b2++)
for(int b3=1;b3<=6;b3++)
if(min(a1,b2)<=min(b1,a2) && min(a2,b3)<=min(a3,b2))
if(min(a3,b1)>min(a1,b3))//这是不满足时的检验.
printf("(%d,%d) (%d,%d) (%d,%d) is WRONG!\n",a1,b1,a2,b2,a3,b3);
(1,2) (1,1) (2,1) is WRONG!
改一改可以有:若任意两个(i,j),(j,k)都满足min(ai,bj)<min(aj,bi),那么必有(i,k)也满足,但是当相等时又该怎么调整呢?
bool FINE(int a1,int b1,int a2,int b2){
if(min(a1,b2)==min(a2,b1)) return a1<a2;
else return min(a1,b2)<min(a2,b1);
}
int main(){
//6个for.
if(FINE(a1,b1,a2,b2) && FINE(a2,b2,a3,b3))
if(!FINE(a1,b1,a3,b3))
printf("(%d,%d) (%d,%d) (%d,%d) is WRONG!\n",a1,b1,a2,b2,a3,b3);
没有输出,则可行,即满足传递性,则可冒泡排序,则可快排.

P5521 [yLOI2019] 梅深不见冬 (提高+/省选-)
把化学反应能量变化图画出来即可,邻项交换后得到(活化能-焓变)最大的最先走.


-----贪心就此告一段落-----后会有期-----


2022/7/9: 我又回来了.
P2123 皇后游戏 (省选/NOI-)
重写思路:在邻项交换时,证明了相邻的i,j只要满足min(ai,bj)<=min(aj,bi),则交换这两个不会更优.但是如果i,j,k三个中i<=j,j<=k均满足,而i<=k不满足这种情况是否存在呢?打一个全排列验证,发现是可能的:(2,1),(1,1),(1,2),此时i和k应该交换一下因为i<=k不成立了...
其实只要记住sort的"严格弱序"要求即可:f(x,x)=false;f(x,y)!=f(y,x);f(x,y) & f(y,z) => f(x,z)=true.
因此将代码改成满足严格弱序后,可以类似于你给每个元素赋一个初值,排序结果是单调不降的;假设有答案与你的排序结果不一样,那么答案肯定会有V形,此时你交换V前两个元素,最终会变为你的结果.

P1645 序列 (提高+/省选-) <- 水题
将需求按R排序,每个需求从右往左填即可,这样对之后的需求不会更差.

P1106 删数问题 (普及/提高-)
为每个位置建立下一个0~9出现的位置的索引,若下一个可填0(需满足0后面的数选一部分或全部能满足要求)则必填.

P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G (普及/提高-)
你的合并即数学归纳法.答案不可能比你更优,因为答案通过不劣的转换,能将当前最小的两个点转为相邻点.

AT4173 [ABC103D] Islands War (暂无评定)
为岛屿标号后,要求即为:在L~R中选择>=1个数,使得总共选的数最少.

AT4500 [AGC029A] Irreversible operation (暂无评定)
把S看成地,W看成方块;操作=将方块往左推一格.

AT4877 [ABC137D] Summer Vacation (普及+/提高)
将工资大到小排(相等时随便).放在尽可能晚的时间完成.肯定不会有后面的工作来替换前面的工作的位置.

AT4720 [ABC123D] Cake 123 (普及+/提高)
题意:三个集合中各选一个数,求相加最大的前k个值.
a+b+c最大的值一定是由最大的a+b中的前k个得来,这就是分解步骤.
对于找两个集合中的最大k个,可以大到小排序后画一个格子图,行列分别表示a和b中的数,用堆每次取出最大并将向上(若为该行首格)和向右的格子加入堆.

P2949 [USACO09OPEN]Work Scheduling G (普及+/提高)
类似的题目,不写了.

P3619 魔法 (普及+/提高)
邻项交换,由于结论只与自己相关,所以肯定满足sort的严格弱序.
另一个妙方法:先减去这些时间,再一个个加上,能加上的条件与b为正时相同.

P2168 [NOI2015] 荷马史诗 (普及+/提高)
编码最短,自然想到哈夫曼树.由于是k进制,故要在一开始就插入一些空节点.在满足贪心的前提下,额外记录当前堆的深度,取深度较浅的可以使得最长单词最短.

P2431 正妹吃月饼 (普及+/提高)
特殊位置为:a,b二进制分解后从高往低找的第一个不同的位(此时必是a=0,b=1),然后贪心的将其改为01111...,不过要特判b在那个位置之后全为1的情况,加个1即可.显然答案不可能改动ab之前相同的位置,在"异位"后最多也就是全填上,不可能更多了.

P6155 修改 (普及+/提高)
将这些数看作一个个泡泡,最终互不相等则视为每个泡泡都进入一个格子(格子是竖着的哈).显然一开始肯定有些泡泡a1单独占据格子,这个格子是不可能让出去的,因为和答案比较,若让出去给了a2,a1到了新的格子,此时所使用的的b1和b2肯定不优于让a2使用min(b1,b2).
然后尽量让移动多的泡泡b小,假设两个泡泡想抢一个格子,它们在之前走过的路程为:a3:c1+c2;a4:c2,那么接下来反正你也不知道是哪个泡泡继续向上浮,不妨就让b小的继续,而a3之前走的路比a4多,因此它的b小.
那么每个空格对应的泡泡就唯一了:离它最近的比它小的泡泡.先由泡泡选出将被入住的格子(unordered_map检验是否该格子为空即可),再让这些格子反向选择泡泡(此时肯定是排好序了的).

P1986 元旦晚会 (普及+/提高)
重题,仅为标记.

AT2044 [AGC004D] Teleporter (提高+/省选-)
首先发现1号节点一定要指向自己,不然如果u点经过v,k步到达1的话,v就不满足要求.(特判菊花)
断掉1连出的边后转变为树,自底向上遍历,一有不满足的点就直接连到1.

P7831 [CCO2021] Travelling Merchant (提高+/省选-)
先干掉-1,然后按照边权从大到小排,每次都准备删边,若当前边u->v是u唯一出边,则u点所需钱数已明确,否则u可以通过走其它边相关的环,不会更劣.
当u点明确后,在反图上走,把一意孤行(仅一条路走到u)的点都求一遍答案并删去正图的边(可以用bool标记边被删去的情况,在check是否唯一出边时注意下就行了).

P2209 [USACO13OPEN]Fuel Economy S (提高+/省选-)
就是"反悔"贪心--花油后才付款,最后多余的油全部退掉.不用管什么距离内最便宜加油站什么的,反正贪心的用最便宜的油.


2022/7/10
P2751 [USACO4.2]工序安排Job Processing (提高+/省选-)
发现AB操作并没有相关性--对于B操作,就算你只知道第几分钟后会有货物出来,照样可行.因此可以拆分这两个操作.
然后A的加工顺序是不断选择结束时间最短的.
对于B,假如物品一开始就全部可以进行加工,那么此时的算法与A是一样的.
然后,把时间想象成柱状条,现在要将其两两拼接使得最长条最短.
显然的,A中最短的拼上B中最长的即可.

P3076 [USACO13FEB]Taxi G (提高+/省选-)
本题应该通过观察,发现空运的路径都源于ed->st(即使一头牛被中途放下),此时将起点设为ed,中点设为st.
然后验证:这样刚好能将所有箭头接起来,所以是可行的.

P6927 [ICPC2016 WF]Swap Space (提高+/省选-)
分为a<=b和a>b的两组,先算第一组,邻项交换可得需满足a1<=a2.那么按照a从小到大排序即可.
接下来出现了皇后游戏时的思考方式!
假设第一组全弄完后剩下了T空间,应该<a1,b1>先于<a2,b2>,则按照此种方法所需的额外空间:
对于a1而言,过程中要买的量为max(a1-T,0).即a1>T时需要额外购买.
对于a2而言:
若a1>T,则现在T'=b1,a2要额外购买max(a2-b1,0),共购买:
a1-T+max(a2-b1,0)=max(a1+a2-T-b1,a1-T).
否则a1<=T,T'=T-a1,a1时没有进行购买,此时a2需要购买:
max(a2-(T-a1+b1),0)=max(a1+a2-T-b1,0)
所以,这个排列需要购买的量为:max(a1+a2-T-b1,a1-T,0).
相应的,交换后需要购买的量为:max(a1+a2-T-b2,a2-T,0).
有上面<=下面,此时尝试去掉0,根据max(A,B)<=max(A,C)等价于((A<=A或A<=C)且(B<=A或B<=C)),它的充分条件是B<=C,也就是说,我使得排列满足B<=C后,肯定会使max的式子成立.
顺便消去一个T,化简为:max(a1-b1+a2,a1)<=(a1+a2-b2,a2)
显然由于a>b,a1-b1+a2>a2,a1<a1+a2-b2,仅需a1-b1+a2<=a1+a2-b2(也可回到上面那个max转换中理解).
因此得出:b1>=b2.
然后手造一组b相同的数据,发现花费相同,以此得出b相同时随便搞.

P1248 加工生产调度 (提高+/省选-)
处理min(a1,b2)<=min(a2,b1)以使得其满足传递性的另一种方法,按照a与b的大小比较,这样可以清晰的说明这三类之间的<=关系.再在同类中相互比较,此时同类中的比较只会保留一个信息,比如a<b的这些中,若a1<a2,则必有a1为四个中最小的;若a1==a2,则这两个都一样,可以视为"相等的数".


2022/7/12
CF549G Happy Line (提高+/省选-)
找出不变量:假设用同位素示踪每一个数,就会发现a[i]+i是不变的,然后只要将其sort并从前往后填即可.

CF798D Mike and distribution (提高+/省选-)
蛮不错的思想:两两一组能保证选出的a>=一半,预先选出一个能去掉等号.
所以按照a大到小排,n=5,选a1后,a1>=max(a2,a3),min(a2,a3)>=max(a4,a5),min(a4,a5)>0.则加起来>一半.然后在每组内选b大的那个即可.

P4053 [JSOI2007] 建筑抢修 (提高+/省选-)
贪心的原则应该是,对于当前时间p,要得到在收益最大前提下的花费最小,这是局部最优性,以此来更新之后的p.
因此按照时间顺序考虑,当i不能塞进去时,则去考虑能否减小花费;否则就把i塞进去.
数学归纳法大概能证明这样是最优的.

P2107 小Z的AK计划 (提高+/省选-)
显然当终点越来越右时加入到{可AK}集合中的数是越来越多的,要在其中选出最小的那些,唯一的要求即为时间,可用动态开点权值线段树维护.
然鹅反过来想一想(因为加入比删去麻烦).逆向思考即可:用一个指针p维护当前选择了1~p(除去其中已被删掉的点),每当删去一个点,验证一下之前是否选中,然后看看p能否往后走.

P8113 [Cnoi2021]自我主义的平衡者 (提高+/省选-)
其实吧,竖着划三条横线,自上到下为p,a1,a2,那么先a2,后a1,p下2的可能仅为第一次在(a1,p);否则第一次仅需在(a2,p)即可.
p若在a1,a2中间,都一样.
p若恰为a1或恰为a2,显然先a1再a2.
p若在a2下方与一开始的分析类似,总之,凡是先a2后a1的方式所能达到的局面,先a1后a2必然亦可以达到甚至更低.排序的依据就出来了.

P3045 [USACO12FEB]Cow Coupons G (提高+/省选-)
有些像"P2107.小Z的AK计划",把原价排序后前缀和,这是预处理出不变量.
接着对于每个优惠券,花掉这点钱后二分剩下能买的原价牛最大量--此时若该优惠券对应的牛又被买了一次,则减去之后看看指针能否后移1位--1位就够了.


2022/7/13
P1484 种树 (提高+/省选-)
反悔贪心的正确性需从费用流角度理解,详见模拟费用流.

P2893 [USACO08FEB] Making the Grade G (提高+/省选-)
要推导一个结论,即答案都可以转换为出现过的数,以此进行离散化后dp.证明很简单,画一个折线图和任意的答案图,将水平段上下平移观察效果即可.

CF865D Buy Low Sell High (提高+/省选-)
贪心的都买后,也就是对于某一个点可以想跟之前的哪一点组队就能组.
考虑最后一天,目前有{2,3,4,5}的票,现在的值是6,显然6和2配对好;
那么倒数第二天是这种情形呢?无论最后一天的数是几,6和2配对仍然不会差,因此第一个结论是--配对当前最小的值.
然后假如2配对了1,最终的最优解应是2作为被配对的出现,那有如何处理?
现在有个3,它先把这个拆了即把1-2改为1-3,答案多了1;
又有个4,配对上了被拆掉的2,答案多了2;
假如之后有5什么的,接下来拆的就是3了.
这时发现--虽然我们给1-2拆开了,但是假如将1-2改为2*(*表示特殊)仍然可以完成上述操作,故1不重要了,忽略掉.
然后再将2*写成两个普通的2.因此得出结论--若某个数y想配对之前的数x,删掉x并加入两个y.

P3545 [POI2012]HUR-Warehouse Store (提高+/省选-)
进货看成一个一个进,类比时间,需求看作工程截止时间和所需时间,完成一个收益+1,就是一个原题了(P4053).

P2587 [ZJOI2008]泡泡堂 (提高+/省选-)
显然这两个问题将数组交换一下就一样了.(A的最低即为B的最高)
然后就是原题:田忌赛马.

P3162 [CQOI2012]组装 (省选/NOI-)
将转折点设置为生产车间自身和两两相同的车间中点--此时这些点之间的距离就是一个二次函数,判断对称轴和两端点关系即可.


2022/7/14
CF730I Olympiad in Programming and Sports (省选/NOI-)
(注:AT2672.二思.)
应该先建立费用流模型,再通过处理"费用流的流量+1"对应的实际操作以减小复杂度.正确性即费用流的正确性.
由此得出费用流共有四种操作:
new->p;new->s;new->p,p->s;new->s,s->p.
3的单价比1多了max(-pi+si)(i表示当前在p内的人,max的结果可能为负);同理,4比2多了max(-si+pi).当改变一个人的归属时建立一个group数组即可.比较时可以顺带带上"关系改变"操作以简化.

P4801 [CCO2015] 饥饿的狐狸 (省选/NOI-)
把一开始喝的水视为一个锤子,饼干视为按照数轴分布的鼠,现在要打掉所有的老鼠,锤子可移回原位(距离不计算).
最小值很容易:显然先打一边,移回来,再打另一边.
最大值额,猜一下是将最远的匹配...不会证明.

P2048 [NOI2010] 超级钢琴 (省选/NOI-)
首先显然要前缀和一下,然后对于每个i,它应该减去左边一个区间的某个数以得到"和弦".显然要用堆,等等!先看看堆中要存放什么东西--由于你的一切选择都只能源自这个堆,因此,一个巧妙的方法是记录此时"可选区间"的范围,当将该struct取出时,让"可选区间"裂开再塞进去.
由此,用st表维护最大值和位置即可.
该内容记录在"堆".

CF436E Cardboard Box (省选/NOI-)
可以思考,如何建立两个集合分别代表1*和2*,且相互无关?(即可以任意选择)
首先显然的是,2*中的元素b-a对应的a不可能出现在1*,不然1*没选它那么2*怎么还能选呢?
那么,为了不断扩展2*(毕竟一开始这里面没有元素嘛),需要找到一个遍历的顺序,使得当前i,1~i-1均必选1*对应的元素,i不明确,i+1~n均最多只能选1*.
要不i也必选1*对应元素a(即可以无忧无虑的选2*),到时候答案取max一下只考虑选1*的即可(较为方便).否则的话,也没差到哪里去.
考虑一下答案的构成,要么全a,否则在排好序后的序列中,必能找到最后一个有b的位置--这个位置是关键,我们希望通过按照某个排序方式使得:它左边全选择了a,剩下的即为2*的待选,右边即为1*的待选.
假设i左边有一个位置j不选a,那么将i的a,b填到该位置上,然后i'为i左边的某个位置,这样可行的前提是bj<=bi.因此排序方式就出来了.

CF1601D Difficult Mountain (省选/NOI-)
假如每个人的a都>=s,那么可以看作n条线段,取不相交(端点不算)的最大数量.
这时反过来思考:对于那些<s的人怎么说?
首先,决不允许的一点是--有a>s的人搞掉了a<=s的人的位置!这个非常容易理解:分析始末状态的需求哪个更严格即可.
那么直接把a<=s的先处理掉--把这些人的a看成一个个极薄的在数轴上的障碍物,然后对于线段而言,不能跨过去就行了.


2022/7/15
AT2672 [AGC018C] Coins (省选/NOI-)
有大佬提供非常妙的思路:由于每个人都必选,则先全选金再调整,为每个人求出(A,B)表示(金->银,金->铜)的收益.
能否经过特定的排序后,使得(金->银)全在1~i中,而(金->铜)全在i+1~n中呢?
也就是说,对于(Bi)(Aj)是不能容忍的,一种可能的原因是,改为(Ai)(Bj)会变得不劣.
也就是Ai+Bj>=Bi+Aj =>按照 A-B 从大到小排序即可.
实现方法是:左边在不断增加,所以小根堆实时维护最大的几个;右边在减少,仅需索引加一个指针即可.

P3620 [APIO/CTSC2007] 数据备份 (省选/NOI-)
没去细看,但好像和之前的种树一致.

P4597 序列 sequence (省选/NOI-)
原题而已.

CF958E2 Guard Duty (medium) (省选/NOI-)
排序后将点之间的距离视为元素,不就是种树了.

P4785 [BalticOI 2016 Day2]交换 (省选/NOI-)
为数进行示踪,发现若一个数被往后换了,它就不可能再往前.
而且一个数最多向前一次.
然后去思考:应该先考虑什么?第一个位置,还是数字1?
显然,假设1在后面(4~n的位置),它就不可能到首位,它就影响不了对于字典序而言最关键的首位!
显然,首位只能由前3个数得来,而且方法唯一,太好了,现在对于2和3位置,...
然而正确性要找任意的点验证,现在有一个普通的点i,它的来源就不仅是2i和2i+1了,思考后发现,i的来源,在没有任何约束的情况下,还可以是:这个结点到根结点的路径上的所有点以及这些点的左儿子.
因此需要备注每个点的类型,使得下面的点向它询问:你能不能下来/你是否已经向下传递过了(每个i最多向下传递一个下标<i的数)等等.

SP1553 BACKUP - Backup Files (省选/NOI-)
原题,略.

CF713C Sonya and Problem Wihtout a Legend (省选/NOI-)
严格单调不降<=>减去下标后非严格单调不降.原题.

CF351E Jeff and Permutation (省选/NOI-)
看一下最大值应该怎么放,答案就出来了吧.


2022/7/16
AT2557 [ARC073C] Ball Coloring (省选/NOI-)
像max,min之类的只与最值相关,那么最小值肯定是Red(Red与Blud等价),再考虑下最大值:
若最大为Blue,就显然了,每组较大的涂成蓝色,较小的涂成红色.
若最大的也为Red,仅需要求Blue的差值最小,忽略2个后将剩下的排序并带着"原本所在组"的信息,类似滑动窗口的方法即可.

AT4993 [AGC034C] Tests (省选/NOI-)
原来如此,s+1,这个sigma肯定变大(先不管>=0),因此要二分答案!
贪心的作用是用当前的材料构造出最优的方案.
这题的构造应该一个一个加,对于i,一开始的收益是l,l,l,(因为c一开始在左),当a=b+1时及之后收益就突然变成r(注,收益表示减去l*b的结果).
因此,一个直观的贪心想法是,要加就加满.证明:对于任意两个未满的ai,aj,比较此时i和j增1得到的收益,取较大的那个让它吸收较小的.由于收益单调不降且亏损(被吸收的那个贡献减少了,即为亏损)单调不升,这个差值恒正.
因此通过调整,至多会有1个是被选取部分的,其余的要么全选要么不选,排序的内容也就呼之欲出了--全选完后R*(X-b)最大的最先.

P7078 [CSP-S2020] 贪吃蛇 (NOI/NOI+/CTSC)
特殊之处是首尾,毫无疑问.
1)尾吃首后不为首,则新尾若吃,会比它更小,更易死,所以新尾会权衡利弊一番,无论如何不会死,故它也不会死.
2)尾吃首后为首,此时新尾和其必为"你死我活"的关系--假如新尾吃掉它后能活,它必死;否则新尾不敢吃它,它就必活.
至于如何判断新尾死活--递归模拟即可,递归中若遇到1),则当前尾必活,不用往下做,因为前一个尾不傻.
因此若遇到2),可以保证在O(n)时间内解决,问题回到了:如何优化1)的时间?
显然原本的队列头尾都会出,所以是双端队列,接下来1)能使得修改后的蛇单调不增(头单不降&尾单不增=相减后单不增)且恒大于原先队列的头(为了满足1),所以一个双端队列足矣.
好题!


2022/7/17
P4823 [TJOI2013]拯救小矮人 (普及/提高-)
先发现,假如答案是最多留下s个人,那么必然存在一种选择,使得s+1个人的最大和>=H;且必然不存在一种选择使得s个人的最大和>=H.
上面的思考是二分答案的前提,那么要设计check函数,check(p)返回,仅保留p个人,是否能爬上来(指的是这p个人的最上面那个).
则需要使得sigma(a)+max(b)最大,有些类似于(P2672.推销员走路),思考答案来源,要么是排序后最大的那些a;要么是最大的a+b和剩下中最大的a.
排序+用st表预处理(a+b)+前缀最大值处理b,那么时间复杂度为O(NlogN),二分的检验则为O(1),二分的总复杂度为O(logN).
(当然,不用st表而是每次check时暴扫也是可以的.)

P5749 [IOI2019]排列鞋子 (提高+/省选-)
显然每个鞋子的归属即从左向右配对,然后配对完成后若左大右小则都取相反数(先后顺序没有关系,最后再交换和一开始就换是一样的).
再考虑最左边的负号,它想和+配对,所需的最小步是一定的,为了清爽一些,就让+不断向左移即可.
接下来问题的模型就是删点+区间求点的个数,线段树维护下就解决了.

P4409 [ZJOI2006]皇帝的烦恼 (提高+/省选-)
相较于贪心,更像动归,见<思想-动归>.

UVA1335 Beijing Guards (提高+/省选-)
与P4409重题了.

P1561 [USACO12JAN]Mountain Climbing S (提高+/省选-)
与P1248重题,本质还是min(a1,b2)<min(a2,b1)的改写.


贪心至此终结,之后零散的补充.

P1937 [USACO10MAR]Barn Allocation G (提高+/省选-)
先猜测一个结论:先排右,相同再比较左.再用数学归纳法+邻项交换证明:当之前已经最优,现在与之前的有冲突时,现在这个不可能被选择.

P2652 同花顺 (提高+/省选-)
很显然,根据贪心原则,肯定要留一种花色不变,那么枚举它就行了.
对于花色a,显然不同花色的都要改,这些数可以改成你"急需"的--比如a1,a3,你缺一个a2,可以刚好补上.然而不能盲目的去补.<贪心-思考答案构成>构成的答案中含有a中最小的元素是哪个?
显然我们要去排序,然后考虑i+1如何继承i的信息.
先是所有答案都可以转变为由a开头的答案,那么i->i+1,它们的末尾位置你都是知道的--a[i]+n/a[i+1]+n,因此记多覆盖的内容[L,R],现在所有属于[L,R+1]的a都可以不改变了,又多了k个,右端点扩展为R+k,然后再继续.
只要实时维护有几个a没改即可.

P3127 [USACO15OPEN]Trapped in the Haybales G (提高+/省选-)
从大到小加入围栏时,假设是L,i,R的状况,若L,i区间就算内部没有障碍物都跑不掉,那么就可以给这个区间宣判死刑了(将L拉一个箭头到R,之后遇到左边是箭头的就跳过);否则将该区间设为"可能可行"的状态.
假设有[A,B]可行,现在要判断的围栏是C,发现[A,C]可行且[A,C]内没有其它障碍物了.
这时肯定能从C一路冲到B的位置,然后就实现了[A,B]随便走的局面,又因为[A,B]可行,又可以冲出去......
若[A,C]内还有障碍物,则该判断等价于为这个区间内部的区间留下一个"期许":若下一个区间能冲破[A,C],就能继续冲破[A,B],最终冲出去.
set是可以的,当然用树状数组模拟平衡树也行.

P3657 [USACO17FEB]Why Did the Cow Cross the Road II P (省选/NOI-)
原来题看错了,奶牛是唯一的,那么匹配数量也是不多的,不妨思考:左边第i个完成匹配后,i+1应该如何回应?
首先,先前完成的匹配可以看成纵横不交错的蜘蛛网,最下端的那条限定了接下来编织的边界,总结下:仅需关心最下方的右端点和该点对应的"已匹配"数量.
那么就呼之欲出了--假如i能和对面的j匹配,那么在1~j-1中找个最大的+1作为用掉j时的答案,显然不可能比原有的更小,因此无需检验,但j要从下往上更新(想想背包问题).

P4404 [JSOI2010]缓存交换 (省选/NOI-)
感觉还是只能先猜后证,不过猜测也是有方向的,每一次放入新内容时要替换原有的值,此时需猜测替换的标准,显然跟已存在的值相关而不是现在的将要加入的值.由样例发现换掉2而不是1,因为先有1.虽然我觉得"要有远见"些,但是该思路可以解释样例,那么就假设"换掉下一次出现最晚的数".
证明:[A,B],之后的出现顺序A前B后,之后序列为~A~B,在A时,若我为[A在B不],则答案为[A不B在],经过B之后,我在这两个位置最多是1的花费,但答案至少是1,而且在A处,答案比我多添加了'A'进去,会对第二个~的内容造成更加不利的影响.而且假设答案将[?...B]改为了[C...B](即?->A->C),我也可以使[A...?]改成[C...B],答案能做的我都能做.

 

 

 

 

 

 

 


备忘,待思考的题:
P4801 [CCO2015] 饥饿的狐狸 (省选/NOI-)
不会最大值的严谨证明.

posted @ 2022-08-01 14:30  Fish_Clever  阅读(398)  评论(0)    收藏  举报