Codeforces Edu 选做记录【连载中】
能力太差了,补一点经典题练练手,尽量 No Editorial。
CF 598D
*1700
上来就吃了坨大的。翻译歧义,注意每个点都能往四联通看一次。卡掉了朴素的记忆化搜索,但是没有关系,统计一下连通块,搜索时合并同时对于块内进行答案覆盖即可,复读什么时间戳优化的题解有点幽默了。
CF 598E
*2000
虚标了,虽然我没想到。一直以为是个神秘贪心,没想到是个朴素 DP,果然看到小的数据范围就要想到有没有可能是状态维数很高的 DP。令 \(f(x, y, s)\) 表示在一个 \(x \times y\) 大小的巧克力上切出大小为 \(s\) 的巧克力的最小代价,分横竖两种可能切:
注意范围,别超过 \(\frac{n}{2}/\frac{m}{2}\) 的范围死递归了。
CF 600C
*1800
没什么难度,主要问题在码上?比较难处理。考虑贪心,桶统计每个字符的出现次数,然后对于奇数情况两两配对消除,如果最后只剩下一个单数情况放在中间。容易发现后者的情况有且仅有一种,不会重复,开桶跑过去就可以了。
CF 609C
*1500
秒了说是。简单贪心题,算出平均数 \(v\) 和余数 \(g\),考虑构造出结果数组 \(b\) 之后和 \(a\) 数组对应位求每一位的贡献,对于 \(b\) 的前 \(n - g\) 个元素赋值为 \(v\),后 \(g\) 个元素赋值为 \(v + 1\),如果想要避免算贡献的时候陷入复杂的 corner case 里,我们可以钦定一个方向比如 \(a_i \gt b_i\) 时算差值累计进答案。
CF 609D
*2000
贪心题,注意到我们对天数 \(x\) 具有可二分性,考虑二分天数之后怎么写这个 \(check\),简单的,贪心找到前 \(x\) 个数中最小的美元和英镑兑换汇率,然后就用这个购买,按照物品代价从小到大排序,如果算出来的购买 \(k\) 物品总和 \(s' \gt s\),返回失败,否则记录结果并返回成功。
CF 612C
*1400
来自十年前的括号匹配 Trick。维护一个栈,做完了。
CF 612D
*1800
翻译的是什么东西啊。差分维护线段覆盖,典。之前一直欠着没有仔细看一遍这次算是补上了。注意到朴素差分覆盖的话,复杂度来到了 \(O(n + V)\),但是前缀和只会在端点处修改,我们存储每个位置对应的类型(\(l\) 还是 \(r\)),拆成 \(2 \times n\) 个节点排序后 \(1 \to 2n\) 扫过去,维护一个前缀和 \(s\),遇到左端点就加,判断是否符合覆盖 \(\geq k\) 的条件,是就更新左端点,遇到右端点判断当前左端点起始覆盖的是否 \(\geq k\),是则累计进答案,然后删除一次覆盖,复杂度 \(O(n \log n)\)。
CF 616D
*1600
双指针,显然答案区间长度具有单调性。类似于滑动窗口,或者说双指针,维护一个左端点 \(l\),\(1 \to n\) 地遍历 \(i\),统计新加入桶的 \(a_i\) 并判断是否加入答案,当区间内不同数字个数 \(c \gt k\) 时,不断移动左端点直到 \(c \leq k\),之后尝试更新答案。
CF 620C
*1500
简单贪心题,\(1e9\) 开不了桶就用 std::map,每次遇到一个重复的数之后立刻断开并清空 std::map,对于最后一段,一定要并到 \(n\)。维护一个全局 \(lst\) 初始为 \(0\),若遍历完了 \([1, n]\) 后 \(lst\) 仍为 \(0\) 则报告无解,否则对于每一段都输出 \([lst + 1, i]\) 并更新 \(lst = i\)。
CF 620D
*2200
简单地,容易想到的是拆式子按照 \(k\) 分类讨论:
- \(k = 0\) 时,输出 \(|s_A - s_B|\)
- \(k = 1\) 时,拆出 \(|s_A - s_B - 2(x + y)|\),枚举交换的两个数 \(x, y\) 即可
- \(k = 2\) 时,类似地拆出 \(|s_A - s_B - 2x - 2x' + 2y + 2y'|\),依旧去枚举 \(x, x'\),对于 \(y, y'\) 我们必然是想要使 \(2(y + y')\) 接近 \(-(s_A - s_B - 2x - 2x')\),预处理出 \(2(y + y')\) 的所有值之后在枚举 \(x, x'\) 的过程中对应的去二分就做完了
码不太好写。
CF 622C
*1500
思维固化了,直接上线段树维护区间最大值最小值及其对应位置,每次查询并检查一下 \(\min = \max\),如果非就输出两者中任意一个不等于 \(x_i\) 的位置。但是正解好像是类似 KMP 的过程跑前驱失配数组。
CF 622D
*1900
简单构造。注意到两个样例的代价都为 \(0\),考虑有没有什么办法一直构造出代价为 \(0\) 的序列。观察式子,显然 \(i = n\) 贡献必为 \(0\),考虑更一般的情况,我们只能使得后一项为 \(0\),此时 \(d_i = n - i\),手玩一下 \(n = 5\) 的情况比较容易发现,直接模拟会出现位置冲突,一个简单的处理方法是分奇偶丢到两个 \(n\) 中分别处理,最后如果有未填充的位置就填上 \(n\)。
CF 622E
*2200
好题且经典。考虑时光倒流,非常有用啊,问题直接转化为了从根出发走到叶子,这个约束就明显比较好做。考虑按照根向下找出最深的叶子,贪心的让某一只蚂蚁先走下去,显然蚂蚁一次只能走一只,从第一只蚂蚁开始后面每只蚂蚁都要等 \(1\) 秒才能接着走,在统计答案过程记录一下等待时间即可,最终答案对从根开始的深度+等待时间取 \(\max\)。
CF 628C
*1300
简单构造题。贪心从前往后尽可能消耗 \(k\),从 \(d(ch, z), d(ch, a)\) 两个角度考虑并替换更改。如果遍历完了字符串 \(k\) 仍有剩余报告无解,若中途出现 \(k = 0\) 的情况钦定后面的字符等于原字符串中对应位置的字符即可。

浙公网安备 33010602011771号