A. Gift Carpet
输入一个 n 行 m 列的字符矩阵,判断矩阵中从前往后的列中能不能找到特定的字符组成 vika
暴力
直接旋转矩阵然后暴力判断 :)
B. Sequence Game
已知 a 序列可以通过特定的规则变化成 b 序列,规则如下:
比如 [4,3,2,6,3,3] 变化为 [4,6,3]
现给出长度为 n 的序列 b ,请构造出符合上述条件的序列 a,长度不能超过 2n
构造
题目要进行一个逆向恢复的过程,由于题目要求构造的序列长度不能超过 2n,先粗略考虑将 b 中的每 1 个元素变成 a 中的 2 个元素。当构造的两个元素相同时,后一个元素aj一定会被添加到 b,而前一个元素当大于等于前一个元素时也可能会被添加到 b 中。出现第二种情况时,aj 就没有必要了。
因此我们可以整理出以下思路:
C. Flower City Fence
输入 n 个数 a,每个 ai 表示高度,n 表示宽度,形成一个类似条形图的图形。
问该图形是否沿直线 x=y 对称
暴力
不太清楚为什么 CF 的标签上会有二分和排序
实际上只需要遍历每个块,判断第 i 个块是否满足第 i 个块的高度a[i]与 j 相等(其中 j 为第一个 a[j]>=i 的值)
写 GO 语言不用读入优化会 TLE on 6
狗都不写 GO
D. Ice Cream Balls
Tema 正在制作双球冰激凌。现在要制作 m 种不同的冰激凌,最少需要几个球?球的种类可以不同,并且有无限多种
注意:不同种类球的放置顺序与产物的种类无关,即1,2=2,1,但 1,1=1,2
组合数学
二分答案
极限情况下,可以每个雪糕球的种类都不相同,这样每取两个就可以形成一种冰激凌,可以保证取到的双球冰激凌种类最多。在这种情况下,每添加一个雪糕球之前已经存在过,那么双球冰激凌种类就会加一。
那么我们可以二分雪糕球的种类 k,每次 check k 种雪糕球能形成的双球冰激凌的种类 A2n2nCn2Cn−22Cn−42…C22=Cn2和m 的关系,保证 Cn2≤m ,最终答案即为 n+(m−Cn2)
根据此其实可以给出一个非二分的写法
若最终有 m 种,则在最优情况下应该是使用了都不相同的雪糕球时 Cn2=2n(n−1)=m
那么 n−1≤2m≤n
令 i=2m,我们只需要尽可能的使 i→n,也就是满足 i(i−1)<=2n 时尽可能大
E. Kolya and Movie Theatre
影院在 n 天中每天放一部新电影。每部电影都有一个价值 ai
当 Kolya 不去看某电影时,下一部电影的价值将下降 d⋅cnt,其中 d 代表预定值,cnt 表示距离上次看电影过了几天。
Kolya 最多只能看 m 次电影,制定一个计划,使 Kolya 的观影价值最大
贪心
如果我们选择 1,3 的电影,答案为a1−(1−0)d+a3−(3−1)d=a1+a3−3d
如果我们选择 1,2,4 的电影,答案为 a1−(1−0)d+a2−(2−1)d+a4−(4−2)d=a1+a2+a4+4d
也就是说无论 Kolya 选择看哪几天的电影,只要最后选择第 k 天的电影,那么价值下降的总和都是 kd,完整的答案为
i∈S∑ai−i∈Smax(i)×d
用优先队列去枚举最大的 S 集合即可
F. Magic Will Save the World
Vika 有水魔法和火魔法,每秒钟 Vika 可以产生 w 单位水魔力和 f 单位火魔力。施展魔法需要魔力,而刚开始 Vika 没有任何魔力。
现在有 n 只怪物,击败每个怪物需要使用消耗 si 魔力的魔法。
Vika 可以在一秒中内无限使用魔法,请求出消灭所有怪物至少需要多少秒
子集枚举
看到这个问题首先想到的是 dp
f[i][j][k]=max(f[i−1][j][k],f[i−1][j−s[i]][k]+1,f[i−1][j][k−s[i]]+1)
但是受限于数据范围 1≤w,f≤109 这样肯定不可行
考虑列出所有怪物血量可组成的集合的子集,枚举子集 i ,计算使用火魔法消灭 i 使用水魔法消灭 sum−i 所需要的时间,统计最小值
G. The Great Equalizer
现有一均衡器设备接受数组 a 作为输入。均衡器将会:
-
升序排序并去重
-
如果当前数组的长度为1 ,均衡器将停止工作,并将数组中唯一的元素作为设备输出
-
在数组中的每个元素加上等差数列 n−0,n−1,n−2,…,1 中对应的元素,其中 n 表示数组长度。即索引从 0 开始时,令第 i 个元素为 a[i]+(n−i)
为了测试设备,将一个数组 a 作为输入,并进行 q 次操作:
-
将 x 赋值给指定元素 ai
-
将数组 a 作为设备的输入,并记录设备的输出。数组 a 在设备运行中保持不变
找出设备每次操作后的输出值
稍微玩一玩样例,可以发现每次操作都可以将两个相邻的两个数的差减小1。也就是说将数组变为相同的一个数需要t=max2≤i≤n(a[i]−a[i−1]) 次操作。最终剩余的数一定是最大的数 a[n]+t
比如 [1,6,10],相邻的两个数最大差 6−1=5,答案即为 10+5=15
直接白嫖 std::multiset
维护集合和相邻两个数的差,每次维护操作复杂度 O(logn)