New Year Snowmen
Description
要堆起一个雪人,需要三个不同大小的雪球。现在有 个给定大小的雪球,问最多能堆起多少个雪人,并输出方案。
Solution
每次用数量最多的三个雪球是最优的。可以用一个单调队列,每次取出最大的三个数,再把余下的丢回队列。
Discounts
Description
超市打折,如果购物车里有至少一个凳子,则可半价购买购物车里最便宜的一个物品。现在你要购买 个物品,其中一些是凳子。你有 个购物车,求一个最优的购买方案,使得花费的价格最少。
Solution
每个购物车的凳子只能优惠价格低于它的,那么优惠它自己是最优的。所以将价格最大的 个凳子放入前 个购物车,余下的购物车放全部的其他物品。
叠罗汉
Description
有 个罗汉,每个罗汉有重量 和力量 。定义一个罗汉的危险值为他上面所有罗汉的重量之和减去他的力量。安排一个顺序使得危险值最大的罗汉的危险值最小。
Solution
如果已经有一个排列,可以对这个排列相邻两个罗汉 和 进行调整, 和 交换不会影响他们上下的人,所以考虑 和 哪个在上面最优,因为要让最大值最小,分类讨论两人的危险值或感性猜测,可发现让两个罗汉中 更小的在上面。最后调整的结果就是将所有罗汉按 从小到大排序。
建筑抢修
Description
基地里有 个建筑设施受到了严重的损伤,但只有 一个修理工人。修复一个建筑都需要 的时间,工人一次只能修一个。如果某个建筑在 时间之内没有修理完毕 ,这个建筑就报废了。你的任务是制订一个合理的维修顺序,以抢修尽可能多的建筑。
Solution
若第 号出现时间不足,那么前 个建筑中最多修复 个建筑。必然选择 较小的前 个建筑,给后面的修复留下更多的时间。按 从小到大排序,中途用堆维护 。如果能修第 个建筑,那么就修,不然从堆中取出所需时间 最大的,如果 就不修 而修 。
反悔性贪心
先能选就选,用堆维护代价最大的,如果不能选看看它能不能替换堆中代价最大的。
密码锁
Description
给定 ,每次操作可以在模 意义下对任意一个区间 整体 或 ,求最少几次操作可以使所有数字变成0。
Solution
在
个数前后补上
,进行在模意义下的差分,有差分数组
,在模意义下的区间加减转为选择一位
,另一位
。要让
全为
或
,先对
从小到大排序。枚举找到一个分界点
,让
左边的数尽可能接近
,
右边的数尽可能接近
,用
左边的数
,右边的数
互相抵消。如果有多余的,可以贪心地控制多余的数尽可能的接近前缀
或后缀
,就可以自己消自己了。
这个式子可以用前缀和预处理搞定。
删数问题
Description
给定一个大正整数 你需要去掉其中任意 位数字。剩下的数字按原次序组成一个新的正整数 。对给定的 和 ,寻找一种方案使得剩下的数字组成的新数 最小。
Solution
要让高位尽可能小。先在数字最后一位补一个 ,输出时忽略掉 。然后从高位向低位枚举,如果在某一个位置数字是递减的,那么将这个位置删掉。如 ,删除如下
如果不够删 个回头重来。
取数游戏
Description
给出 个正整数,你需要把它们连接成一排,组成一个最大的多位整数。
Solution
重载 的定义,如果 与 拼接比 与 拼接大,就认为 。按照重载的小于号从小到大排序即可。如 和 ,虽然数学中 ,但是因为 ,所以 。
Main Sequence
Description
定义幸运数列:空序列是幸运序列。如果 为幸运数列,有一个正整数 ,那么 也是幸运序列。如果 和 都是幸运序列,那么 也是幸运序列。现在给你一个有 个元素的序列每个数的绝对值,同时有 个限制,每个限制为数列的第 个数一定为负数。请你求出这个幸运数列。
Solution
这道题就是一个括号匹配, 可以看作是左括号, 可以看作是右括号。因为 个右括号已经确定了,所以我们从后往前扫这个序列。相似的,我们用栈来维护右括号,对于每个数有两种情况,如果他是 个数之一或者不能与栈顶的右括号匹配,那么让他加入未匹配的右括号栈中,否则我们将栈顶的数退栈,表示匹配成功。如果将序列扫完栈不为空,则匹配失败。
兔子和樱花
Description
给定一颗 的点的有根树,每个点 上面有一些樱花 ,设 为 父亲, 为父亲的儿子数。现在可以删掉一些节点,被删除的节点 的樱花会累加到 上, 的子节点也会接到 上。要求删除完 后, 。问最多能删多少个点。
Solution
从下向上进行树形 dp,对于每个点,删除的代价为 ,我们对于每个点尽可能多地从小到大删它的儿子。
Assassin Creed
Description
你是一个刺客,有把耐久度为 的刀,你要杀死 个敌人,其中杀死第 个敌人需要消耗 点耐久度,但可以得到一把能杀死 个敌人的武器(不消耗自己的耐久度)。问最多可以杀死多少个敌人。以及在这个前提下,最少需要消耗的耐久度。
Solution
- 先杀一个 中 最小的人,借刀杀掉所有 的人,如果还有刀,就杀掉剩下 最大的人。最后用自己的刀把 尽可能小的一些人杀掉。但是还存在一种情况,对于 的人,不用敌人的刀杀死他而用自己的刀就有可能杀掉更多的人。
- 可能 的人 都非常大,所以可能只能杀 尽可能小的一些人。
打游戏
Description
Solution
先将 个怪从小到大排序,然后依次打。如果场上最小怪的生命值为 时能放群攻,就放群攻,如果怪的个数 能放群攻放群攻,如果只有两个怪且他们生命值 时从小到打能放重击放重击。
DFS Spanning Tree
Description
给出一个没有自环的有向图。这个图的前 条边构成这个图的一个以节点 为根节点的 dfs 树。T-Simple 环的定义是:至多有一条边不在这棵树上的环。至少在图上选中多少条边。才使得每个 T-simple 环都至少有一条边被选中。
Solution
题目给出了是 dfs 序的树,可以发现,除了树上的边就只有返祖边。每条非树边都相当于在 dfs 生成树上划定了一条深度单调的链,问题转化为最少染色多少条边,可以使每条链上都至少有一条边被染色。
先考虑一个不在树上的子问题, 有一个序列,现在有 个限制条件。第 个限制是, 到 的这段区间内至少有一个位置被打标记。问至少要打几个标记。可以从左往右扫,对于每个没有标记的限制条件 就贪心地在 打一个标记。
那么这个问题就是把数列改成了一棵树,把限制放在树上,直接树形 dp 即可。
乐曲创作
Description
给你一个 个数的排列 ,设它有 个逆序对。现在要求找出字典序大于原序列最小的排列,使它逆序对的个数也等于 。
Solution
令 为构造的数组,那么有一个 满足 且 。最优的 一定是在 尽可能靠后的前提下, 在 尽可能小的前提下尽可能的小。
所以从后往前找到一个 ,首先满足他后面有至少一个比它大的数。其次,我们把一个数交换成比它大的最小的数,会造成多的逆序对,如果 的数按照从小到大排列,那么 的逆序对个数最少,在最少的情况下,逆序对总数还 ,那么我们就只能放弃这个 去枚举之前的 。否则,我们一定有策略让 的逆序对总数 。可以证明,对于第二个限制,只要 中有至少一个逆序对,那么一定有策略让 的逆序对总数 。
确定 后, 与 相同, 为 中 的最小的数,接下来要从 往后做构造 。我们找到了 ,那么已经搞定了 的字典序 的问题和无论如何安排数逆序对总数都 的问题 ,对于 的构造,要让越往前的位置安排的数尽可能的小,如果我们在 安排了一个 的数,那么逆序对总数会减少。如果 按照从大到小排列,那么 的逆序对个数最多,在最多的情况下,逆序对总数还 ,那么我们要在位置 安排一个大一点的数。
Shop
Description
现在有 个数 。有三种操作, , 与 ,其中 和 为给定参数。现在给你 以上个操作,你能从中最多选出 个并自行安排顺序,要求操作完后 个数的乘积最大。
Solution
可以发现先进行 ,再进行 ,最后进行 是最优的。考虑将前两种操作转换成第三种。对于第一种操作通过 转成第二种,第二种可以通过 求出倍率。然后全部成为操作三了,从大到小排序求。这样做并不违背之前的规律,因为乘法的顺序和乘在哪个 上是没关系的。但是输出的时候一定要按照先赋值再加最后乘的顺序。值得一提的是,对于同一个数的赋值保留最大的。
Color a tree
修理牛棚 Barn Repair
Description
有一排共 个牛棚,有的牛棚有牛。请你用不超 块木板盖住有牛的牛棚,木板长度自定。求最小木板长度和。
Solution
逆向思维贪心。 用一个长度为 的木板盖住所有的牛棚,可以发现盖了没有牛的牛棚,于是我们可以删一段木板,每删一段木板,木板数会多一个,所以可以删 次木板。删木板根据贪心思想,删去长度要尽可能的长,但还不能将有牛的牛棚删掉。所以我们可以将所有的没有牛的牛棚找出来,将每个连续的一段的长度排序,从大到小删即可。
Bohater
Description
你需要打败 只怪物。打败第 只怪物需要消耗 点生命值,但怪物死后会掉落血药,使你恢复 点生命值。任何时候你的生命值都不能降到零及以下。求是否存在打怪顺序,使得你可以打完这 只怪物而不死掉。
Solution
为了打更多的怪,我们想办法先回血,而且先回尽可能多的血,不过想先回血要先消耗生命值。那么将打怪消耗的血量从小到大排序,将能打的怪用一个堆维护,优先取出回血多的怪,打完一个怪后看看能不能加一些怪进堆。
护花
Description
有 只牛,第 头每分钟吃 朵花,可以让第 头牛不吃花,但过 分钟后 才能让下一头牛不吃花,求牛最少吃多少花。
Solution
将 ,考虑相邻的两头牛交换顺序,第一头在第二头前面为 ,第二头在第一头前面为 ,如果前式小于后式,那么第一头排在第二头前面,所以自定义比较函数排个序。
优惠券
Description
有 本书,第 本书花费 元,有 张优惠券,一张优惠券可以让第 本书降价到 元,求 元能买多少书。
Solution
考虑选哪 本书使用优惠券,对于两本书,如果一本用优惠券另一本直接买,若第一本书用优惠券,那么花费为 ,第二本书用优惠券花费为 ,如果前式小于后式,那么第一本书用优惠券,移项的话成了 ,所以将所有书按差值从小到大排序,选最小的 本书用优惠券。还有钱的话将其他书的 从小到大排序依次买。
奶酪工厂
Description
有 个星期,第 个星期生产一个单位奶酪花费 分,多余生产的可以放在仓库,一个星期一个单位花 分。第 个星期需要 个单位的奶酪,求最小花费。
Solution
要么全部生产,要么全部从仓库取,所以在仓库屯有史以来最便宜的货,即为维护最小值,取货时比较一下两个情况。
均分纸牌
Description
有 堆纸牌,每堆有若干张,总和为 的倍数。每次可以将任意张牌从一堆移到与它相邻的一堆。求最少移动多少次才能让每堆纸牌数目相同。
Solution
显然相邻两堆只用移动一次。可以发现左右的移动可以归于一个左边向右边移动可正负张纸牌,所以求前缀和和纸牌平均数。从头扫,假设扫到了第 张纸牌,如果第 张纸牌需要向右移动当且仅当到 的前缀和不等于 平均数。操作是可逆的,所以不存在第 张牌不能向右移的尴尬。