贪心+构造练习
菜就多练。
贪心和构造有一定相似性(都不会做),放在一起做吧。
1. [ABC123D] Cake 123
热身简单题。利用堆进行贪心。
发现排序后都取端点一定是最值,然后随便一个序列中向后挪一个位置都有可能是次大值。
于是用堆维护,每次弹出最大的,然后向后拓展三个状态塞到堆里面。注意可能一个状态会被多次拓展到,要标记去重。
反正数据范围小,\(O(k\log k)\)(?,总之能过。
另一种做法是先求前两个序列中前\(k\)个和,再用这些数与第三个序列求前\(k\)个和。
2. P6155 修改
排序不等式,邻项交换,直觉。
首先注意到修改过的数要尽量少,可以随便证一下。
由排序不等式,假设已经求出每个数的修改次数,那么就按排序不等式逆序和加起来。
来求每个数的修改次数,先把原数组排序,考虑在值域上依次枚举,维护一个集合\(S\)表示手上还没被用来填值域的数。
枚举到\(v\)时,把等于\(v\)的原数组中的数插入到\(S\)中,现在考虑从\(S\)中取哪一个数进行若干次修改到\(v\)。
如果\(S\)中有\(v\),那就直接填。如果没有,可以证明用\(S\)中最接近\(v\)的数去填是最优的,考虑邻项交换。
注意到\(S\)中插入的数按插入顺序单增,且都\(\le v\),于是用栈维护一下\(S\)就好。注意如果枚举到一段值域上时\(S=\emptyset\),需要跳过这一段。
\(O(n)\)。
3. [AGC004D] Teleporter
树上贪心,从叶子考虑。关注不变的事情(不争的事实),关注答案的形态。
发现有\(n\)个点\(n\)条边,且都能到\(1\),于是画一下就知道是一棵基环树。
首先可以证明\(1\)一定是自环:若不是,设\(u\)到\(1\)经过\(k\)步,那么\(fa_u\)到\(1\)就不是\(k\)步,矛盾。
于是可以转化题意为:以\(1\)为根的一棵树,要使得最大深度\(\le k\),最小化操作次数。
关注一些总是不变的事情:最深的叶子在操作后的深度恰好为\(k\)。否则,我们总是可以调整修改的边,使之尽可能向上,因为这样总是可能让操作的子树包括其他深度超过\(k\)的点。
于是DFS,过程中如果当前子树的高度为\(k\),那就操作一次,并且使这棵子树对上方节点计算子树高度的影响为\(0\)。
\(O(n)\)。
4. [AGC007B] Construct Sequences
看到单调性构造想差分。利用反函数性质将下标化简。
\(\{a_n\}\)单调递增,\(\{b_n\}\)单调递减,那么差分一下,设:
来看剩下的限制,为了\(a_{p_i}+b_{p_i}>a_{p_{i-1}}+b_{p_{i-1}}\),我们尝试令\(a_{p_k}+b_{p_k}=C+k\)。
为了利用上差分,我们代换一下,设\(q_{p_k}=p_{q_k}=k\),即\(q\)是\(p\)的反函数。对上面的式子中的\(k\)同时作用上一个\(q\),可以得到\(a_{p_{q_k}}+b_{p_{q_k}}=C+q_k\)即\(a_k+b_k=C+q_k\)。
尝试相邻两项相减来做差分,即\((a_k+b_k)-(a_{k-1}+b_{k-1})=x_k-y_{k-1}=q_k-q_{k-1}\)。
于是一组合法的解为\(x_k=y_k=q_k\)。\(q\)由\(p\)可以求得,于是\(a_k=\sum\limits_{j\le k}q_j,b_k=\sum\limits_{j\ge k} q_j\)即可。
5. P4053 [JSOI2007] 建筑抢修
反悔贪心,先随便贪然后设计反悔。
首先随便贪,但要有一定的正确性。这里的限制主要是报废时间,于是报废时间小的要先做。
如果做到一个位置不得不报废了,就查看要不要反悔,如果之前做过的最长耗时比这个位置的用时长,那么用这次的替换之显然更优,因为使得总用时减小了,并且这样一定不会使当前位置报废。
就这样反悔,用大根堆维护最长耗时,\(O(n\log n)\)。
也有不反悔的做法,正着做,每个任务显然要尽量在贴近报废时去做,并且优先做用时少的,用线段树/ODT维护区间推平即可,\(O(n\log n)\)。
6. P2209 [USACO13OPEN] Fuel Economy S
最直接的想法是,每次到一个费用比较小的加油站再加油。
那么可以这样想,每次到一个加油站,我们都想判断能不能到一个费用比它更小的加油站加油。
于是首先可以单调栈搞出来每个位置后面第一个费用比它小的。
由于有油箱大小的限制,判断在不加爆油箱的前提下,能否通过加一些油走到下一个比它费用更小的加油站。如果可以,就这么干,否则直接把油箱加满,往前走。
这样是因为如果到不了,那么最终必然会走到一个费用比它大的位置,不如当前加满油箱。
是 greedy stays ahead 的想法。
7. P7831 [CCO 2021] Travelling Merchant
发现首先可以类似拓扑排序地判掉一些不在环中的点。其实是先建反图,然后拓扑排序。于是现在剩下了一些环。
考察当前图中 \(r\) 最大的一条边,可以发现原图上 \(ans_u\le r\)。发现有类似 DP 的东西,\(ans_u=\min\{\max\{ans_v-p,r\}\}\),但是最大的问题是有环。对于 \(r\) 最大的边,用 \(r\) 更新答案之后断掉它。这是可能又出现了类似 DAG 的结构,刚才的 DP 就可以做了。重复这个过程即可。
正确性考虑当我们断掉一条边产生了类似 DAG 的结构时,必然存在点一定要走到经过它的环中,用它来更新显然正确。
类似不断更新上界,最后最优秀的上界就是答案。
8. P2587 [ZJOI2008] 泡泡堂
完全体田忌赛马。