Description
要堆起一个雪人,需要三个不同大小的雪球。现在有 n n n 个给定大小的雪球,问最多能堆起多少个雪人,并输出方案。
Solution
每次用数量最多的三个雪球是最优的。可以用一个单调队列,每次取出最大的三个数,再把余下的丢回队列。
Description
超市打折,如果购物车里有至少一个凳子,则可半价购买购物车里最便宜的一个物品。现在你要购买 n n n 个物品,其中一些是凳子。你有 k k k 个购物车,求一个最优的购买方案,使得花费的价格最少。
Solution
每个购物车的凳子只能优惠价格低于它的,那么优惠它自己是最优的。所以将价格最大的 k − 1 k-1 k−1 个凳子放入前 k − 1 k - 1 k−1 个购物车,余下的购物车放全部的其他物品。
Description
有 n n n 个罗汉,每个罗汉有重量 w w w 和力量 s s s。定义一个罗汉的危险值为他上面所有罗汉的重量之和减去他的力量。安排一个顺序使得危险值最大的罗汉的危险值最小。
Solution
如果已经有一个排列,可以对这个排列相邻两个罗汉 i i i 和 j j j 进行调整, i i i 和 j j j 交换不会影响他们上下的人,所以考虑 i i i 和 j j j 哪个在上面最优,因为要让最大值最小,分类讨论两人的危险值或感性猜测,可发现让两个罗汉中 w + s w+s w+s 更小的在上面。最后调整的结果就是将所有罗汉按 w + s w + s w+s 从小到大排序。
Description
基地里有 n n n 个建筑设施受到了严重的损伤,但只有 一个修理工人。修复一个建筑都需要 t i t_i ti 的时间,工人一次只能修一个。如果某个建筑在 d i d_i di 时间之内没有修理完毕 ,这个建筑就报废了。你的任务是制订一个合理的维修顺序,以抢修尽可能多的建筑。
Solution
若第 i i i 号出现时间不足,那么前 i i i 个建筑中最多修复 i − 1 i-1 i−1 个建筑。必然选择 t i t_i ti 较小的前 i − 1 i-1 i−1 个建筑,给后面的修复留下更多的时间。按 d d d 从小到大排序,中途用堆维护 t m a x t_{max} tmax。如果能修第 i i i 个建筑,那么就修,不然从堆中取出所需时间 t t t 最大的,如果 t m a x > t i t_{max} > t_i tmax>ti 就不修 m a x max max 而修 i i i。
先能选就选,用堆维护代价最大的,如果不能选看看它能不能替换堆中代价最大的。
Description
给定 a [ 1 ∼ n ] , a i ∈ [ 0 , m − 1 ] a[1 \sim n], a_i \in [0,m-1] a[1∼n],ai∈[0,m−1],每次操作可以在模 m m m 意义下对任意一个区间 [ l , r ] [l,r] [l,r] 整体 + 1 +1 +1 或 − 1 -1 −1,求最少几次操作可以使所有数字变成0。
Solution
在 n n n 个数前后补上 0 0 0,进行在模意义下的差分,有差分数组 b b b,在模意义下的区间加减转为选择一位 + 1 +1 +1,另一位 − 1 -1 −1。要让 b b b 全为 0 0 0 或 m m m,先对 b b b 从小到大排序。枚举找到一个分界点 m i d mid mid,让 m i d mid mid 左边的数尽可能接近 0 0 0, m i d mid mid 右边的数尽可能接近 m m m ,用 m i d mid mid 左边的数 + 1 +1 +1,右边的数 − 1 -1 −1 互相抵消。如果有多余的,可以贪心地控制多余的数尽可能的接近前缀 0 0 0 或后缀 0 0 0,就可以自己消自己了。
a n s = m a x { ∑ i = 1 m i d b i , ∑ i = m i d + 1 n m − b i } ans = max\{ \sum_{i = 1} ^ {mid} b_i, \sum_{i = mid + 1} ^ {n} m - b_i\} ans=max{i=1∑midbi,i=mid+1∑nm−bi}
这个式子可以用前缀和预处理搞定。
Description
给定一个大正整数 S S S 你需要去掉其中任意 n n n 位数字。剩下的数字按原次序组成一个新的正整数 S ’ S’ S’。对给定的 n n n 和 S S S,寻找一种方案使得剩下的数字组成的新数 S ’ S’ S’ 最小。
Solution
要让高位尽可能小。先在数字最后一位补一个 − 1 -1 −1,输出时忽略掉 − 1 -1 −1。然后从高位向低位枚举,如果在某一个位置数字是递减的,那么将这个位置删掉。如 S = 178543 , n = 4 S = 178543,n = 4 S=178543,n=4,删除如下
178543 { 8 } 178543 \quad \{ 8 \} 178543{8} → \to → 17543 { 7 } 17543\quad\{ 7 \} 17543{7} → \to → 1543 { 5 } 1543\quad\{ 5 \} 1543{5} → \to → 143 { 4 } 143\quad\{ 4 \} 143{4} → \to → 13 13 13
如果不够删 n n n 个回头重来。
Description
给出 n n n 个正整数,你需要把它们连接成一排,组成一个最大的多位整数。
Solution
重载 < < < 的定义,如果 a a a 与 b b b 拼接比 b b b 与 a a a 拼接大,就认为 a > b a > b a>b。按照重载的小于号从小到大排序即可。如 12 12 12 和 121 121 121,虽然数学中 121 > 12 121 > 12 121>12,但是因为 12121 > 12112 12121 > 12112 12121>12112,所以 12 > 121 12 > 121 12>121。
Description
定义幸运数列:空序列是幸运序列。如果 S S S 为幸运数列,有一个正整数 k k k,那么 { k , S , − k } \{k, S, -k\} {k,S,−k} 也是幸运序列。如果 S S S 和 T T T 都是幸运序列,那么 { S + T } \{S+T\} {S+T} 也是幸运序列。现在给你一个有 n n n 个元素的序列每个数的绝对值,同时有 m m m 个限制,每个限制为数列的第 i i i 个数一定为负数。请你求出这个幸运数列。
Solution
这道题就是一个括号匹配, k k k 可以看作是左括号, − k -k −k 可以看作是右括号。因为 m m m 个右括号已经确定了,所以我们从后往前扫这个序列。相似的,我们用栈来维护右括号,对于每个数有两种情况,如果他是 m m m 个数之一或者不能与栈顶的右括号匹配,那么让他加入未匹配的右括号栈中,否则我们将栈顶的数退栈,表示匹配成功。如果将序列扫完栈不为空,则匹配失败。
Description
给定一颗 n n n 的点的有根树,每个点 x x x 上面有一些樱花 a x a_x ax,设 f a x fa_x fax 为 x x x 父亲, s o n f a x son_{fa_x} sonfax为父亲的儿子数。现在可以删掉一些节点,被删除的节点 x x x 的樱花会累加到 f a x fa_x fax 上, x x x 的子节点也会接到 f a x fa_x fax 上。要求删除完 x x x 后, a f a x + s o n f a x < m a_{fa_x} + son_{fa_x} < m afax+sonfax<m。问最多能删多少个点。
Solution
从下向上进行树形 dp,对于每个点,删除的代价为 c i + s o n i c_i + son _i ci+soni,我们对于每个点尽可能多地从小到大删它的儿子。
Description
你是一个刺客,有把耐久度为 M M M 的刀,你要杀死 N N N 个敌人,其中杀死第 i i i 个敌人需要消耗 A i A_i Ai 点耐久度,但可以得到一把能杀死 B i B_i Bi 个敌人的武器(不消耗自己的耐久度)。问最多可以杀死多少个敌人。以及在这个前提下,最少需要消耗的耐久度。
Solution
Description
先将 n n n 个怪从小到大排序,然后依次打。如果场上最小怪的生命值为 1 1 1 时能放群攻,就放群攻,如果怪的个数 > 2 >2 >2 能放群攻放群攻,如果只有两个怪且他们生命值 ≥ 2 \ge 2 ≥2 时从小到打能放重击放重击。
Description
给出一个没有自环的有向图。这个图的前 n − 1 n-1 n−1 条边构成这个图的一个以节点 1 1 1 为根节点的 dfs 树。T-Simple 环的定义是:至多有一条边不在这棵树上的环。至少在图上选中多少条边。才使得每个 T-simple 环都至少有一条边被选中。
Solution
题目给出了是 dfs 序的树,可以发现,除了树上的边就只有返祖边。每条非树边都相当于在 dfs 生成树上划定了一条深度单调的链,问题转化为最少染色多少条边,可以使每条链上都至少有一条边被染色。
先考虑一个不在树上的子问题, 有一个序列,现在有 n n n 个限制条件。第 i i i个限制是, L i L_i Li 到 R i R_i Ri 的这段区间内至少有一个位置被打标记。问至少要打几个标记。可以从左往右扫,对于每个没有标记的限制条件 x x x 就贪心地在 R x R_x Rx 打一个标记。
那么这个问题就是把数列改成了一棵树,把限制放在树上,直接树形 dp 即可。
Description
给你一个 n n n 个数的排列 a [ 1 ∼ n ] a[1 \sim n] a[1∼n] ,设它有 m m m 个逆序对。现在要求找出字典序大于原序列最小的排列,使它逆序对的个数也等于 m m m。
Solution
令 b b b 为构造的数组,那么有一个 p p p 满足 a 1 ∼ p − 1 = b 1 ∼ p − 1 a_{1 \sim p - 1} = b_{1 \sim p - 1} a1∼p−1=b1∼p−1 且 a p ≤ b p a_p \leq b_p ap≤bp。最优的 b b b 一定是在 p p p 尽可能靠后的前提下, i ∈ b [ p + 1 , n ] a i i \in b_{[p + 1,n]} \ a_{i} i∈b[p+1,n] ai 在 a i − 1 a_{i-1} ai−1 尽可能小的前提下尽可能的小。
所以从后往前找到一个 p p p,首先满足他后面有至少一个比它大的数。其次,我们把一个数交换成比它大的最小的数,会造成多的逆序对,如果 [ p + 1 , n ] [p+1,n] [p+1,n] 的数按照从小到大排列,那么 [ 1 , n ] [1,n] [1,n] 的逆序对个数最少,在最少的情况下,逆序对总数还 > m > m >m,那么我们就只能放弃这个 p p p 去枚举之前的 p p p。否则,我们一定有策略让 [ 1 , n ] [1,n] [1,n] 的逆序对总数 = m =m =m。可以证明,对于第二个限制,只要 [ p + 1 , n ] [p+1, n] [p+1,n] 中有至少一个逆序对,那么一定有策略让 [ 1 , n ] [1,n] [1,n] 的逆序对总数 = m =m =m。
确定 p p p 后, b [ 1 , p − 1 ] b_{[1,p - 1]} b[1,p−1] 与 a [ 1 , p − 1 ] a_{[1,p - 1]} a[1,p−1] 相同, b p b_p bp 为 a [ p + 1 , n ] a_{[p + 1, n]} a[p+1,n] 中 > a p >a_p >ap 的最小的数,接下来要从 p p p 往后做构造 b [ p + 1 , n ] b_{[p + 1,n]} b[p+1,n]。我们找到了 p p p,那么已经搞定了 b b b 的字典序 > a > a >a 的问题和无论如何安排数逆序对总数都 > m > m >m 的问题 ,对于 b [ p + 1 , n ] b_{[p + 1,n]} b[p+1,n] 的构造,要让越往前的位置安排的数尽可能的小,如果我们在 i ∈ b [ p + 1 , n ] a i i \in b_{[p + 1,n]} a_{i} i∈b[p+1,n]ai 安排了一个 < a i
Description
现在有 n n n 个数 a i a_i ai 。有三种操作, a i = b a_i = b ai=b, a i + b a_i + b ai+b 与 a i × b a _i \times b ai×b,其中 i i i 和 b b b 为给定参数。现在给你 m m m 以上个操作,你能从中最多选出 k k k 个并自行安排顺序,要求操作完后 n n n 个数的乘积最大。
Solution
可以发现先进行 a i = b a_i = b ai=b ,再进行 a i + b a_i + b ai+b,最后进行 a i × b a_i \times b ai×b 是最优的。考虑将前两种操作转换成第三种。对于第一种操作通过 b − a i b - a_i b−ai 转成第二种,第二种可以通过 ( a i + b ) a i \frac{(a_i + b)}{a_i} ai(ai+b) 求出倍率。然后全部成为操作三了,从大到小排序求。这样做并不违背之前的规律,因为乘法的顺序和乘在哪个 a i a_i ai 上是没关系的。但是输出的时候一定要按照先赋值再加最后乘的顺序。值得一提的是,对于同一个数的赋值保留最大的。
Description
有一排共 n n n 个牛棚,有的牛棚有牛。请你用不超 m m m 块木板盖住有牛的牛棚,木板长度自定。求最小木板长度和。
Solution
逆向思维贪心。 用一个长度为 n n n 的木板盖住所有的牛棚,可以发现盖了没有牛的牛棚,于是我们可以删一段木板,每删一段木板,木板数会多一个,所以可以删 m − 1 m - 1 m−1 次木板。删木板根据贪心思想,删去长度要尽可能的长,但还不能将有牛的牛棚删掉。所以我们可以将所有的没有牛的牛棚找出来,将每个连续的一段的长度排序,从大到小删即可。
Description
你需要打败 n n n 只怪物。打败第 i i i 只怪物需要消耗 d i d_i di 点生命值,但怪物死后会掉落血药,使你恢复 a i a_i ai 点生命值。任何时候你的生命值都不能降到零及以下。求是否存在打怪顺序,使得你可以打完这 n n n 只怪物而不死掉。
Solution
为了打更多的怪,我们想办法先回血,而且先回尽可能多的血,不过想先回血要先消耗生命值。那么将打怪消耗的血量从小到大排序,将能打的怪用一个堆维护,优先取出回血多的怪,打完一个怪后看看能不能加一些怪进堆。
Description
有 n n n 只牛,第 i i i 头每分钟吃 d i d_i di 朵花,可以让第 i i i 头牛不吃花,但过 2 × t i 2 \times t_i 2×ti 分钟后 才能让下一头牛不吃花,求牛最少吃多少花。
Solution
将 t i × 2 t_i \times 2 ti×2,考虑相邻的两头牛交换顺序,第一头在第二头前面为 d 1 + d 2 × t 1 d_1 + d_2 \times t1 d1+d2×t1,第二头在第一头前面为 d 1 × t 2 + d 2 d_1 \times t_2 + d_2 d1×t2+d2,如果前式小于后式,那么第一头排在第二头前面,所以自定义比较函数排个序。
Description
有 n n n 本书,第 i i i 本书花费 p i p_i pi 元,有 k k k 张优惠券,一张优惠券可以让第 i i i 本书降价到 c i c_i ci 元,求 m m m 元能买多少书。
Solution
考虑选哪 k k k 本书使用优惠券,对于两本书,如果一本用优惠券另一本直接买,若第一本书用优惠券,那么花费为 c 1 + p 2 c_1 + p_2 c1+p2,第二本书用优惠券花费为 c 2 + p 1 c_2 + p_1 c2+p1,如果前式小于后式,那么第一本书用优惠券,移项的话成了 p 1 − c 1 < p 2 − c 2 p_1 - c_1 < p_2 - c_2 p1−c1<p2−c2,所以将所有书按差值从小到大排序,选最小的 k k k 本书用优惠券。还有钱的话将其他书的 p i p_i pi 从小到大排序依次买。
Description
有 n n n 个星期,第 i i i 个星期生产一个单位奶酪花费 c i c_i ci 分,多余生产的可以放在仓库,一个星期一个单位花 S S S 分。第 i i i 个星期需要 a i a_i ai 个单位的奶酪,求最小花费。
Solution
要么全部生产,要么全部从仓库取,所以在仓库屯有史以来最便宜的货,即为维护最小值,取货时比较一下两个情况。
Description
有 n n n 堆纸牌,每堆有若干张,总和为 n n n 的倍数。每次可以将任意张牌从一堆移到与它相邻的一堆。求最少移动多少次才能让每堆纸牌数目相同。
Solution
显然相邻两堆只用移动一次。可以发现左右的移动可以归于一个左边向右边移动可正负张纸牌,所以求前缀和和纸牌平均数。从头扫,假设扫到了第 i i i 张纸牌,如果第 i i i 张纸牌需要向右移动当且仅当到 i i i 的前缀和不等于 i × i \times i× 平均数。操作是可逆的,所以不存在第 n n n 张牌不能向右移的尴尬。
Linl