「CSPS 2019 十一」 贪心

一般来说,如果题目需要求一个最优解或者最小(大)花费之类的,而且除了暴力之外想不到什么好方法,那么就可能需要用贪心。

通常地,我们猜想一些步骤能不能直接使用贪心,然后再去证明这个贪心是对的。

有时候可能要多想几种贪心才能找到正确的那一种。

New Year Snowmen

Description

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

Solution

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


Discounts

Description

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

Solution

每个购物车的凳子只能优惠价格低于它的,但是优惠价格减小了还不如不优惠。所以将价格最大的 \(k-1\) 个凳子放入前 \(k - 1\) 个购物车,余下的购物车放全部的其他物品。


叠罗汉

Description

有 \(n\) 个罗汉,每个罗汉有重量 \(w\) 和力量 \(s\)。定义一个罗汉的危险值为他上面所有罗汉的重量之和减去他的力量。安排一个顺序使得危险值最大的罗汉的危险值最小。

Solution

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


建筑抢修

Description

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

Solution

若第 \(i\) 号出现时间不足,那么前 \(i\) 个建筑中最多修复 \(i-1\) 个建筑。必然选择 \(t_i\) 较小的前 \(i-1\) 个建筑,给后面的修复留下更多的时间。按 \(d\) 从小到大排序,中途用堆维护 \(t_{max}\)。如果能修第 \(i\) 个建筑,那么就修,不然从堆中取出所需时间 \(t\) 最大的,如果 \(t_{max} > t_i\) 就不修 \(max\) 而修 \(i\)。


扁鹊再世蔡徐坤

Description

因为版权原因,不放题面。

Solution

如果某个方案中存在一个人不能被镇静,把他去掉可以让其他人分到更多的量,答案只会更优。令 \(s_i\) 为每个人满意的情况下能够接受的最大的分子 。如果从大到小枚举 \(s_i\) 最小的人,可以选的人越来越多。但因为 \(a_i\) 之和应小于 \(s_i\),所以选择 \(a_i\) 最小的一些人,这个过程可以用堆来维护,将枚举的人加入优先队列,再从队列中不断弹出 \(a_i\) 最大的人直到 \(a_i\) 之和 \(\leq s_i\)。


密码锁

Description

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

Solution

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

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


删数问题

Description

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

Solution

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

\(178543 \{ 8 \}\) \(\quad\) \(17543\{ 7 \}\) \(\quad\) \(1543\{ 5 \}\) \(\quad\) \(143\{ 4 \}\) \(\quad\) \(13\)


取数游戏

Description

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

Solution

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


Main Sequence

Description

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

Solution

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


兔子和樱花

Description

给定一颗 \(n\) 的点的有根树,每个点 \(x\) 上面有一些樱花 \(a_x\),设 \(fa_x\) 为 \(x\) 父亲,\(son_{fa_x}\)为父亲的儿子数。现在可以删掉一些节点,被删除的节点 \(x\) 的樱花会累加到 \(fa_x\) 上,\(x\) 的子节点也会接到 \(fa_x\) 上。要求删除完 \(x\) 后,\(a_{fa_x} + son_{fa_x} < m\)。问最多能删多少个点。

Solution

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


刺客

Description

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

Solution

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

打游戏

Description

因为版权原因,不放题面。

Solution

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


DFS Spanning Tree

Description

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

Solution

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

先考虑一个不在树上的子问题, 有一个序列,现在有 \(n\) 个限制条件。第 \(i\)个限制是,\(L_i\) 到 \(R_i\) 的这段区间内至少有一个位置被打标记。问至少要打几个标记。可以从左往右扫,对于每个没有标记的限制条件 \(x\) 就贪心地在 \(R_x\) 打一个标记。

那么这个问题就是把数列改成了一棵树,把限制放在树上。按树的 dfs 序从前往后像序列上那样处理就可以了。


乐曲创作

Description

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

Solution

令 \(b\) 为构造的数组,那么有一个 \(p\) 满足 \(a_{1 \sim p - 1} = b_{1 \sim p - 1}\) 且 \(a_p \leq b_p\)。最优的 \(b\) 一定是在 \(p\) 尽可能靠后的前提下,\(i \in b_{[p + 1,n]} \ a_{i}\) 在 \(a_{i-1}\) 尽可能小的前提下尽可能的小。

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

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


Shop

Description

现在有 \(n\) 个数 \(a_i\) 。有三种操作,\(a_i = b\),\(a_i + b\) 与 \(a _i \times b\),其中 \(i\) 和 \(b\) 为给定参数。现在给你 \(m\) 以上个操作,你能从中最多选出 \(k\) 个并自行安排顺序,要求操作完后 \(n\) 个数的乘积最大。

Solution

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


Color a tree

Description

给定一棵有 \(n\) 个节点的树,每个节点有一个权值 \(W_i\),你需要从前往后一个一个地把点安放进数组 \(a\) 中。\(a\) 需要满足若点 \(a_i\) 为 \(a_j\) 的父亲,则 \(i\) 必须小于 \(j\) 。一种安放方案的权值为 \(\sum_{i=1}^n W_{a[i]} \times i\),请找出权值最小的方案并输出最小权值。

Solution

如果没有父节点排在节点之前的限制,就可以按照权值从大到小排序的顺序选。虽然这道题要求父节点必须在所有子节点前面,但是也可以仿照没有限制的思路。对于一个权值极大的点,如果没有限制的话我们越早放这个点越好,但是有限制的话,就必须将这个点与他的父亲绑定在一起,一旦他的父亲放了,就紧挨着他的父亲放进去。

先不考虑如何绑定节点,而是考虑一个子问题,如果在保持这个紧挨着的绑定关系同时,其他节点不作限制,我们应该如何排列呢? 我们假设绑定在一起的两节点是 \(A\) 和 \(B\) 。现有另外一个节点 \(X\),我们观察两种排列 \(XAB\),\(ABX\) 对最终的计算结果有什么影响,假设第一个数的位置在序列中是 \(i\) ,这两个排列带来的权值分别是:
\[
Value_1 = W_X \times i+W_A \times (i+1) + W_B \times (i+2)
\]

\[
Value_2 = W_A \times i+W_B \times (i+1) + W_X \times (i+2)
\]

显然是谁的 \(Value\) 小就按照谁排序,如果我们用 \(Value_2 - Value_1 = 2 \times W_x - (W_A + W _B)\),如果式子结果 \(>0\),那么就选前者,否则选后者。进一步地,我们比较的是 \(\frac{W_A + W_B}{2}\) 与 \(\frac{W_x}{1}\)。发现这个东西,有点像平均数?尝试把结论推广到确定两个序列的关系上,找一找规律,发现真的就是平均数。也就是说,设一个序列 \(W_1\) 有 \(N\) 个节点,另一个序列 \(W_2\) 的序列有 \(M\) 个节点,我们可以比较 \(\frac{ \sum_{i=1}^N W_{1_i}}{N}\) 与 \(\frac{ \sum_{i=1}^M W_{2_i}}{M}\)。我们将 \(W_1\) 和 \(W_2\) 的平均值称为 \(C_i\)。

最后考虑如何绑定节点的问题,一开始,每个序列只有一个点,他们的 \(C_i\) 就是 \(W_i\),每次操作把 \(C_i\) 最大的点合并到他的父节点并记录贡献,一直合并到根节点即可。



「CSPS 2019 十一」 贪心

原文地址:https://www.cnblogs.com/lyfoi/p/11618253.html

时间: 2024-10-07 03:22:47

「CSPS 2019 十一」 贪心的相关文章

「CSPS 2019 十一」三地联考

因为版权原因,不放题面. 幸福 Solution 只会写 \(70\) 分的找规律代码,可以考虑每个斐波那契数对卷积的贡献,发现贡献是类似于倒斐波那契数列,就可以 \(O(n)\) 做了,有 \(70\) 分. std 是化简一下式子,化简结果为 \[F_n = F_{n-1} + F_{n-2} + f_n\] 发现这是一个递推式,用矩阵乘法加速即可.但是我不会矩阵乘法,先咕了.不会矩阵乘法也可以用退出来的递推式拿 \(70\) 分. Code #include <bits/stdc++.h>

「CSPS 2019 十一」数据结构

栈与队列 单调栈,单调队列,优先队列. 蚯蚓 Description 给你一堆数,有 \(n\) 个,并对他们操作 \(m\) 次.每次取出最大的一个数 \(x\),称之为母数.并将 \(x\) 分割成左端数 \([x \times p]\) 和右端数 \(x-[p \times x]\),并把这两个数放回数堆中,其余数均增加 \(q\) .\(p\) 固定为 \((0,1)\) 的有理数.要求输出每次操作的数x和m次操作后所有数的和. Solution 对于 $85% $ 的数据,是可以用优先

LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例

二次联通门 : LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例 /* LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例 很显然 贪心方程哦不 dp方程为 f[i][j]=f[i-1][j-k*k] 但是这样的话复杂度就是O(N ^ 5) 那么就用bitset优化一下 就ok了 */ #include <iostream> #include <cstdio> #include <bitset> void

「CSP-S模拟赛」2019第二场

目录 T1 Jam的计数法 题目 考场思路(正解) T2 「TJOI / HEOI2016」排序 题目 考场思路(假正解) 正解 T3 「THUWC 2017」随机二分图 题目 考场思路 正解 这场考试的数据感觉很水. \(T1\) 签到不解释,\(T2\) 期望 \(50pts\) 结果有 \(100pts\),\(T3\) 一如既往地不可做... ___ T1 Jam的计数法 题目 点这里 考场思路(正解) 其实没有什么好说的,找找规律即可,看看代码吧. #include<cstdio>

「CSP-S模拟赛」2019第一场

目录 T1 小奇取石子 题目 考场思路 正解 T2 「CCO 2017」专业网络 题目 考场思路 题解 T3 「ZJOI2017」线段树 题目 考场思路 正解 这场考试感觉很奇怪. \(T1.T2\) 都缺一个小特判. \(T3\) 打了个比暴力优的暴力 还是暴力,但是不知道为什么 \(WA\) 穿了. 考试的时候还玩扫雷... 其实,菜是原罪啊... ___ T1 小奇取石子 题目 点这里 考场思路 刚开始差点被自己坑了,开考 \(5min\) 就码出了一个可以惨痛爆零的 \(01\) 背包.

Loj515 「LibreOJ β Round #2」贪心只能过样例 - Bitset,Dp

bitset的基本应用了 类似可行性背包的dp考虑 复杂度O(nmL/64) 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 bitset <1000005> bs,bs0; 5 6 int n,a,b; 7 8 int main(){ 9 ios::sync_with_stdio(false); 10 cin>>n; 11 bs[0]=1; 12 for(int i=1;i<=n;i++){ 13 bs

loj 3014「JOI 2019 Final」独特的城市

loj 我本来是直接口胡了一个意思一样的做法的,但是因为觉得有点假+实现要用并查集(?)就卡了好一会儿... 对于一个点\(x\)来说,独特的点一定在它的最长链上,如果有独特的点不在最长链上,那么最长链上一定有和他到\(x\)距离相同的点,矛盾 然后对于一个点,最长链端点一定可以是直径的两端点之一,所以如果我们分别以树的直径的两端点为根进行dfs,那么一个点在其中一次dfs中,独特的点都会在到根的路径上,所以我们用栈维护到根的点,然后不同颜色数开桶来维护,每次压栈或弹栈时改变桶内元素个数,然后根

LiberOJ 6003. 「网络流 24 题」魔术球 贪心或者最小路径覆盖

6003. 「网络流 24 题」魔术球 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有 n nn 根柱子,现要按下述规则在这 n nn 根柱子中依次放入编号为 1,2,3,4,? 1, 2, 3, 4, \cdots1,2,3,4,? 的球. 每次只能在某根柱子的最上面放球. 在同一根柱子中,任何 2 22 个相邻球的编号之和为完全平方数. 试设计一个算法,计算出在 

#3144. 「APIO 2019」奇怪装置

#3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个结论:该装置是一个特殊的时钟,它从过去的某个时间点开始测量经过的时刻数 \(t\),但该装置的创造者却将 \(t\) 用奇怪的方式显示出来.若从该装置开始测量到现在所经过的时刻数为 \(t\),装置会显示两个整数:\(x = ((t + \lfloor \frac{t}{B} \rfloor) \b