贪心+构造练习

菜就多练。

贪心和构造有一定相似性(都不会做),放在一起做吧。

1. [ABC123D] Cake 123

link

热身简单题。利用进行贪心。

发现排序后都取端点一定是最值,然后随便一个序列中向后挪一个位置都有可能是次大值。

于是用堆维护,每次弹出最大的,然后向后拓展三个状态塞到堆里面。注意可能一个状态会被多次拓展到,要标记去重。

反正数据范围小,O(klogk)(?,总之能过。

另一种做法是先求前两个序列中前k个和,再用这些数与第三个序列求前k个和。

2. P6155 修改

link

排序不等式,邻项交换,直觉。

首先注意到修改过的数要尽量少,可以随便证一下。

排序不等式,假设已经求出每个数的修改次数,那么就按排序不等式逆序和加起来。

来求每个数的修改次数,先把原数组排序,考虑在值域上依次枚举,维护一个集合S表示手上还没被用来填值域的数。

枚举到v时,把等于v的原数组中的数插入到S中,现在考虑从S中取哪一个数进行若干次修改到v

如果S中有v,那就直接填。如果没有,可以证明用S中最接近v的数去填是最优的,考虑邻项交换

注意到S中插入的数按插入顺序单增,且都v,于是用栈维护一下S就好。注意如果枚举到一段值域上时S=,需要跳过这一段。

O(n)

3. [AGC004D] Teleporter

link

树上贪心,从叶子考虑。关注不变的事情(不争的事实),关注答案的形态

发现有n个点n条边,且都能到1,于是画一下就知道是一棵基环树。

首先可以证明1一定是自环:若不是,设u1经过k步,那么fau1就不是k步,矛盾。

于是可以转化题意为:以1为根的一棵树,要使得最大深度k,最小化操作次数。

关注一些总是不变的事情:最深的叶子在操作后的深度恰好为k。否则,我们总是可以调整修改的边,使之尽可能向上,因为这样总是可能让操作的子树包括其他深度超过k的点。

于是DFS,过程中如果当前子树的高度为k,那就操作一次,并且使这棵子树对上方节点计算子树高度的影响为0

O(n)

4. [AGC007B] Construct Sequences

link

看到单调性构造想差分。利用反函数性质将下标化简。

{an}单调递增,{bn}单调递减,那么差分一下,设:

akak1=xkbkbk+1=ykak=jkxjbk=jkyj其中1xj,yj,ak,bk109

来看剩下的限制,为了api+bpi>api1+bpi1,我们尝试令apk+bpk=C+k

为了利用上差分,我们代换一下,设qpk=pqk=k,即qp的反函数。对上面的式子中的k同时作用上一个q,可以得到apqk+bpqk=C+qkak+bk=C+qk

尝试相邻两项相减来做差分,即(ak+bk)(ak1+bk1)=xkyk1=qkqk1

于是一组合法的解为xk=yk=qkqp可以求得,于是ak=jkqj,bk=jkqj即可。

5. P4053 [JSOI2007] 建筑抢修

link

反悔贪心,先随便贪然后设计反悔。

首先随便贪,但要有一定的正确性。这里的限制主要是报废时间,于是报废时间小的要先做。

如果做到一个位置不得不报废了,就查看要不要反悔,如果之前做过的最长耗时比这个位置的用时长,那么用这次的替换之显然更优,因为使得总用时减小了,并且这样一定不会使当前位置报废。

就这样反悔,用大根堆维护最长耗时,O(nlogn)

也有不反悔的做法,正着做,每个任务显然要尽量在贴近报废时去做,并且优先做用时少的,用线段树/ODT维护区间推平即可,O(nlogn)

posted @   RandomShuffle  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示