New Year Snowmen

Description

要堆起一个雪人,需要三个不同大小的雪球。现在有 nn 个给定大小的雪球,问最多能堆起多少个雪人,并输出方案。

Solution

每次用数量最多的三个雪球是最优的。可以用一个单调队列,每次取出最大的三个数,再把余下的丢回队列。


Discounts

Description

超市打折,如果购物车里有至少一个凳子,则可半价购买购物车里最便宜的一个物品。现在你要购买 nn 个物品,其中一些是凳子。你有 kk 个购物车,求一个最优的购买方案,使得花费的价格最少。

Solution

每个购物车的凳子只能优惠价格低于它的,那么优惠它自己是最优的。所以将价格最大的 k1k-1 个凳子放入前 k1k - 1 个购物车,余下的购物车放全部的其他物品。


叠罗汉

Description

nn 个罗汉,每个罗汉有重量 ww 和力量 ss。定义一个罗汉的危险值为他上面所有罗汉的重量之和减去他的力量。安排一个顺序使得危险值最大的罗汉的危险值最小。

Solution

如果已经有一个排列,可以对这个排列相邻两个罗汉 iijj 进行调整,iijj 交换不会影响他们上下的人,所以考虑 iijj 哪个在上面最优,因为要让最大值最小,分类讨论两人的危险值或感性猜测,可发现让两个罗汉中 w+sw+s 更小的在上面。最后调整的结果就是将所有罗汉按 w+sw + s 从小到大排序。


建筑抢修

Description

基地里有 nn 个建筑设施受到了严重的损伤,但只有 一个修理工人。修复一个建筑都需要 tit_i 的时间,工人一次只能修一个。如果某个建筑在 did_i 时间之内没有修理完毕 ,这个建筑就报废了。你的任务是制订一个合理的维修顺序,以抢修尽可能多的建筑。

Solution

若第 ii 号出现时间不足,那么前 ii 个建筑中最多修复 i1i-1 个建筑。必然选择 tit_i 较小的前 i1i-1 个建筑,给后面的修复留下更多的时间。按 dd 从小到大排序,中途用堆维护 tmaxt_{max}。如果能修第 ii 个建筑,那么就修,不然从堆中取出所需时间 tt 最大的,如果 tmax>tit_{max} > t_i 就不修 maxmax 而修 ii

反悔性贪心

先能选就选,用堆维护代价最大的,如果不能选看看它能不能替换堆中代价最大的。


密码锁

Description

给定 a[1n],ai[0,m1]a[1 \sim n], a_i \in [0,m-1],每次操作可以在模 mm 意义下对任意一个区间 [l,r][l,r] 整体 +1+11-1,求最少几次操作可以使所有数字变成0。

Solution

nn 个数前后补上 00,进行在模意义下的差分,有差分数组 bb,在模意义下的区间加减转为选择一位 +1+1,另一位 1-1。要让 bb 全为 00mm,先对 bb 从小到大排序。枚举找到一个分界点 midmid,让 midmid 左边的数尽可能接近 00midmid 右边的数尽可能接近 mm ,用 midmid 左边的数 +1+1,右边的数 1-1 互相抵消。如果有多余的,可以贪心地控制多余的数尽可能的接近前缀 00 或后缀 00,就可以自己消自己了。
ans=max{i=1midbi,i=mid+1nmbi} ans = max\{ \sum_{i = 1} ^ {mid} b_i, \sum_{i = mid + 1} ^ {n} m - b_i\}

这个式子可以用前缀和预处理搞定。


删数问题

Description

给定一个大正整数 SS 你需要去掉其中任意 nn 位数字。剩下的数字按原次序组成一个新的正整数SS’。对给定的 nnSS,寻找一种方案使得剩下的数字组成的新数 SS’ 最小。

Solution

要让高位尽可能小。先在数字最后一位补一个 1-1,输出时忽略掉 1-1。然后从高位向低位枚举,如果在某一个位置数字是递减的,那么将这个位置删掉。如 S=178543,n=4S = 178543,n = 4,删除如下

178543{8}178543 \quad \{ 8 \} \to 17543{7}17543\quad\{ 7 \} \to 1543{5}1543\quad\{ 5 \} \to 143{4}143\quad\{ 4 \} \to 1313

如果不够删 nn 个回头重来。


取数游戏

Description

给出 nn 个正整数,你需要把它们连接成一排,组成一个最大的多位整数。

Solution

重载 << 的定义,如果 aabb 拼接比 bbaa 拼接大,就认为 a>ba > b。按照重载的小于号从小到大排序即可。如 1212121121,虽然数学中 121>12121 > 12,但是因为 12121>1211212121 > 12112,所以 12>12112 > 121


Main Sequence

Description

定义幸运数列:空序列是幸运序列。如果 SS 为幸运数列,有一个正整数 kk,那么 {k,S,k}\{k, S, -k\} 也是幸运序列。如果 SSTT 都是幸运序列,那么 {S+T}\{S+T\} 也是幸运序列。现在给你一个有 nn 个元素的序列每个数的绝对值,同时有 mm 个限制,每个限制为数列的第 ii 个数一定为负数。请你求出这个幸运数列。

Solution

这道题就是一个括号匹配kk 可以看作是左括号,k-k 可以看作是右括号。因为 mm 个右括号已经确定了,所以我们从后往前扫这个序列。相似的,我们用栈来维护右括号,对于每个数有两种情况,如果他是 mm 个数之一或者不能与栈顶的右括号匹配,那么让他加入未匹配的右括号栈中,否则我们将栈顶的数退栈,表示匹配成功。如果将序列扫完栈不为空,则匹配失败。


兔子和樱花

Description

给定一颗 nn 的点的有根树,每个点 xx 上面有一些樱花 axa_x,设 faxfa_xxx 父亲,sonfaxson_{fa_x}为父亲的儿子数。现在可以删掉一些节点,被删除的节点 xx 的樱花会累加到 faxfa_x 上,xx 的子节点也会接到 faxfa_x 上。要求删除完 xx 后,afax+sonfax<ma_{fa_x} + son_{fa_x} < m。问最多能删多少个点。

Solution

从下向上进行树形 dp,对于每个点,删除的代价为 ci+sonic_i + son _i,我们对于每个点尽可能多地从小到大删它的儿子。


Assassin Creed

Description

你是一个刺客,有把耐久度为 MM 的刀,你要杀死 NN 个敌人,其中杀死第 ii 个敌人需要消耗 AiA_i 点耐久度,但可以得到一把能杀死 BiB_i 个敌人的武器(不消耗自己的耐久度)。问最多可以杀死多少个敌人。以及在这个前提下,最少需要消耗的耐久度。

Solution

  1. 先杀一个 Bi>0B_i > 0AiA_i 最小的人,借刀杀掉所有 Bi>0B_i > 0 的人,如果还有刀,就杀掉剩下 AiA_i 最大的人。最后用自己的刀把 AiA_i 尽可能小的一些人杀掉。但是还存在一种情况,对于 Bi>0B_i > 0 的人,不用敌人的刀杀死他而用自己的刀就有可能杀掉更多的人。
  2. 可能 Bi>0B_i > 0 的人 AiA_i 都非常大,所以可能只能杀 AiA_i 尽可能小的一些人。

打游戏

Description

刷题系列——贪心

Solution

先将 nn 个怪从小到大排序,然后依次打。如果场上最小怪的生命值为 11 时能放群攻,就放群攻,如果怪的个数 >2>2 能放群攻放群攻,如果只有两个怪且他们生命值 2\ge 2 时从小到打能放重击放重击。


DFS Spanning Tree

Description

给出一个没有自环的有向图。这个图的前 n1n-1 条边构成这个图的一个以节点 11 为根节点的 dfs 树。T-Simple 环的定义是:至多有一条边不在这棵树上的环。至少在图上选中多少条边。才使得每个 T-simple 环都至少有一条边被选中。

Solution

题目给出了是 dfs 序的树,可以发现,除了树上的边就只有返祖边。每条非树边都相当于在 dfs 生成树上划定了一条深度单调的链,问题转化为最少染色多少条边,可以使每条链上都至少有一条边被染色

先考虑一个不在树上的子问题, 有一个序列,现在有 nn 个限制条件。第 ii个限制是,LiL_iRiR_i 的这段区间内至少有一个位置被打标记。问至少要打几个标记。可以从左往右扫,对于每个没有标记的限制条件 xx 就贪心地在 RxR_x 打一个标记。

那么这个问题就是把数列改成了一棵树,把限制放在树上,直接树形 dp 即可。


乐曲创作

Description

给你一个 nn 个数的排列 a[1n]a[1 \sim n] ,设它有 mm 个逆序对。现在要求找出字典序大于原序列最小的排列,使它逆序对的个数也等于 mm

Solution

bb 为构造的数组,那么有一个 pp 满足 a1p1=b1p1a_{1 \sim p - 1} = b_{1 \sim p - 1}apbpa_p \leq b_p。最优的 bb 一定是在 pp 尽可能靠后的前提下,ib[p+1,n] aii \in b_{[p + 1,n]} \ a_{i}ai1a_{i-1} 尽可能小的前提下尽可能的小。

所以从后往前找到一个 pp,首先满足他后面有至少一个比它大的数。其次,我们把一个数交换成比它大的最小的数,会造成多的逆序对,如果 [p+1,n][p+1,n] 的数按照从小到大排列,那么 [1,n][1,n] 的逆序对个数最少,在最少的情况下,逆序对总数还 >m> m,那么我们就只能放弃这个 pp 去枚举之前的 pp。否则,我们一定有策略让 [1,n][1,n] 的逆序对总数 =m=m。可以证明,对于第二个限制,只要 [p+1,n][p+1, n] 中有至少一个逆序对,那么一定有策略让 [1,n][1,n] 的逆序对总数 =m=m

确定 pp 后,b[1,p1]b_{[1,p - 1]}a[1,p1]a_{[1,p - 1]} 相同,bpb_pa[p+1,n]a_{[p + 1, n]}>ap>a_p 的最小的数,接下来要从 pp 往后做构造 b[p+1,n]b_{[p + 1,n]}。我们找到了 pp,那么已经搞定了 bb 的字典序 >a> a 的问题和无论如何安排数逆序对总数都 >m> m 的问题 ,对于 b[p+1,n]b_{[p + 1,n]} 的构造,要让越往前的位置安排的数尽可能的小,如果我们在 ib[p+1,n]aii \in b_{[p + 1,n]} a_{i} 安排了一个 <ai<a_i 的数,那么逆序对总数会减少。如果 [i+1,n][i+1,n] 按照从大到小排列,那么 [1,n][1,n] 的逆序对个数最多,在最多的情况下,逆序对总数还 <m<m,那么我们要在位置 ii 安排一个大一点的数。


Shop

Description

现在有 nn 个数 aia_i 。有三种操作,ai=ba_i = bai+ba_i + bai×ba _i \times b,其中 iibb 为给定参数。现在给你 mm 以上个操作,你能从中最多选出 kk 个并自行安排顺序,要求操作完后 nn 个数的乘积最大。

Solution

可以发现先进行 ai=ba_i = b ,再进行 ai+ba_i + b,最后进行 ai×ba_i \times b 是最优的。考虑将前两种操作转换成第三种。对于第一种操作通过 baib - a_i 转成第二种,第二种可以通过 (ai+b)ai\frac{(a_i + b)}{a_i} 求出倍率。然后全部成为操作三了,从大到小排序求。这样做并不违背之前的规律,因为乘法的顺序和乘在哪个 aia_i是没关系的。但是输出的时候一定要按照先赋值再加最后乘的顺序。值得一提的是,对于同一个数的赋值保留最大的。


Color a tree


修理牛棚 Barn Repair

Description

有一排共 nn 个牛棚,有的牛棚有牛。请你用不超 mm 块木板盖住有牛的牛棚,木板长度自定。求最小木板长度和。

Solution

逆向思维贪心。 用一个长度为 nn 的木板盖住所有的牛棚,可以发现盖了没有牛的牛棚,于是我们可以删一段木板,每删一段木板,木板数会多一个,所以可以删 m1m - 1 次木板。删木板根据贪心思想,删去长度要尽可能的长,但还不能将有牛的牛棚删掉。所以我们可以将所有的没有牛的牛棚找出来,将每个连续的一段的长度排序,从大到小删即可。


Bohater

Description

你需要打败 nn 只怪物。打败第 ii 只怪物需要消耗 did_i 点生命值,但怪物死后会掉落血药,使你恢复 aia_i 点生命值。任何时候你的生命值都不能降到零及以下。求是否存在打怪顺序,使得你可以打完这 nn 只怪物而不死掉。

Solution

为了打更多的怪,我们想办法先回血,而且先回尽可能多的血,不过想先回血要先消耗生命值。那么将打怪消耗的血量从小到大排序,将能打的怪用一个堆维护,优先取出回血多的怪,打完一个怪后看看能不能加一些怪进堆。


护花

Description

nn 只牛,第 ii 头每分钟吃 did_i 朵花,可以让第 ii 头牛不吃花,但过 2×ti2 \times t_i 分钟后 才能让下一头牛不吃花,求牛最少吃多少花。

Solution

ti×2t_i \times 2,考虑相邻的两头牛交换顺序,第一头在第二头前面为 d1+d2×t1d_1 + d_2 \times t1,第二头在第一头前面为 d1×t2+d2d_1 \times t_2 + d_2,如果前式小于后式,那么第一头排在第二头前面,所以自定义比较函数排个序。


优惠券

Description

nn 本书,第 ii 本书花费 pip_i 元,有 kk 张优惠券,一张优惠券可以让第 ii 本书降价到 cic_i 元,求 mm 元能买多少书。

Solution

考虑选哪 kk 本书使用优惠券,对于两本书,如果一本用优惠券另一本直接买,若第一本书用优惠券,那么花费为 c1+p2c_1 + p_2,第二本书用优惠券花费为 c2+p1c_2 + p_1,如果前式小于后式,那么第一本书用优惠券,移项的话成了 p1c1<p2c2p_1 - c_1 < p_2 - c_2,所以将所有书按差值从小到大排序,选最小的 kk 本书用优惠券。还有钱的话将其他书的 pip_i 从小到大排序依次买。


奶酪工厂

Description

nn 个星期,第 ii 个星期生产一个单位奶酪花费 cic_i 分,多余生产的可以放在仓库,一个星期一个单位花 SS 分。第 ii 个星期需要 aia_i 个单位的奶酪,求最小花费。

Solution

要么全部生产,要么全部从仓库取,所以在仓库屯有史以来最便宜的货,即为维护最小值,取货时比较一下两个情况。


均分纸牌

Description

nn 堆纸牌,每堆有若干张,总和为 nn 的倍数。每次可以将任意张牌从一堆移到与它相邻的一堆。求最少移动多少次才能让每堆纸牌数目相同。

Solution

显然相邻两堆只用移动一次。可以发现左右的移动可以归于一个左边向右边移动可正负张纸牌,所以求前缀和和纸牌平均数。从头扫,假设扫到了第 ii 张纸牌,如果第 ii 张纸牌需要向右移动当且仅当到 ii 的前缀和不等于 i×i \times 平均数。操作是可逆的,所以不存在第 nn 张牌不能向右移的尴尬。

相关文章: