【2019】CSP-J2 / S2 简要题解 + 总结
Cefola_Kiroxs · · 个人记录
简要题解
J-T1 数字游戏
需要说什么吗(
J-T2 交通换乘
我们可以将对于每一次公交车,可以使用的地铁票的条件概括为三点:
-
时间差小于等于 45 分钟
-
票价大于等于当前公交车的价钱
-
满足上述条件的地铁票中,时间最早的
注意到题目的读入是依照时间顺序的,所以只要我们维护一个队列,每次及时弹出 “时间差大于 45 分钟” 的队首元素,那么在剩下的元素里,从前往后第一个满足 “票价大于等于当前公交车的价钱” 的地铁票肯定是符合题目要求的(原理显然)。
我们使用一个票不一定能及时弹出去,所以我们要打个标记,表示是否使用过;相应的,在每次弹出队首元素时如果碰到使用过的票,则也要弹出。但也许会有一个疑问 —— 如果使用过的票不及时弹出,那么会不会队列每次要遍历很久才能找到一个未使用的票?不会,因为地铁的时间是互不相同的,所以算法的时间复杂度至多为
J-T3 纪念品
首先,考虑只有一个物品的情况。 每个方案无非就是由若干个 “持有 —— 卖出” 纪念品组成,那么有两种情况(约定
- 只存在于第
i 天买入,在第i+1 天卖出的情况,则我们这样考虑:视该纪念品的重量w_i = a_i ,价值为v_i = a_{i+1} - a_{i} ,则可以将本题转换为一个T 天、1 个物品的完全背包模型(有物品件数、背包容量、物品的价值和重量,并且每个物品选的件数不限)。
注意这里存在一个性质 —— 由于第
- 存在于第
i 天买入,在第k(k > i+1) 天卖出的情况,则我们可能要考虑第i 天时该物品买入的时间,这样复杂度就大大提高了。我们试着将这种复杂的情况归约到简单的情况(上一种情况)上。
注意到题目里 “当日购买的纪念品也可以当日卖出换回金币” 这句话,它提示我们 —— 对于上述第二种情况,可以将其拆解为第
关注其与第一种情况的共同点,则我们易想到 —— 强制每一个纪念品在第
接下来扩展到
算法的时间复杂度为 register 优化跑过本题还是绰绰有余的。
J-T4 零件加工
S-D1-T1 格雷码
根据题面显而易见可得(
对着做就行,记得 ull 就行。
S-D1-T2 括号树
首先,注意到题目中有两个关键点:
-
题目的核心是,求出括号序列中合法的括号序列子串的个数。
-
题目给定了一个树,任意两个结点间有且仅有一条简单路径。
有经验的选手可以快速想到,我们可以利用动态规划的思想,设
用栈求解括号序列子串的个数,这应该是提高组 OIer 的必备技能,这里不多提了,不过稍微提及状态设计的一个要点。注意到对于任意结点
下面直接给出状态转移方程。设
-
先将
pre_i = pre_{root_i} (也就是假设未匹配的左括号没有减少、没有增加),方便下面表示。 -
当
a_i 为左括号时,v_i = 0 ,pre_i = i (未匹配的左括号增加)。 -
当
a_i 为右括号,且有可以匹配的左括号时,v_i = 1 + v_{root_{pre_i}} (也就是说,当前这个新的匹配能与v_{root_{pre_i}} 个括号序列连起来,组成新的答案),pre_i = pre_{root_{pre_i}} (pre_i 已经被匹配掉了)。
算法的时间复杂度为
已知失误
-
每道题打暴力时间过长 (S-D1,如果每道题能节省打暴力的时间,切 T1 甚至 T2 都是有可能的)
-
过高估计自己思考 T2 & T3 的能力,过低估计自己思考 T1 的能力(因此没敢仔细思考 T1) (S-D1,如果减少打 T2 和 T3 暴力的时间,切 T1 那是毫无压力的)
-
状态过于紧张,思考进展过慢、且不够充分 (S-D1,大概是过于紧张,所以 T1 的思路进展很慢;而且,由于 T1 思考实在不充分,匆匆忙忙就去打暴力,还调了一段时间,可能也有影响思路)
-
没养成遍历树用 BFS 的习惯 (S-D1 和 S-D2 均有,虽然似乎对分数没太大影响,但还是留点心)
-
对拍、测小数据十分不用心 (S-D1,T2 如果认真对拍,对着题目给出的各种情况调试程序,我的暴力分估计就拿满了)
-
没掌握 “部分分推广到正解” 的思路和技巧 (S-D1,T2 可以非常简单地从部分分推广到正解,很可惜我没有写出部分分,但如果写出来,可能也没有 “化链为树” 的意识,所以要留点心)
-
没有 “改变状态定义” 的意识 (S-D1,T2 如果将状态定义改为 “以当前结点为结尾” 的话就好办多了)
-
指数级复杂度的超时判断十分复杂,最好不要这么做 (S-D2,T2 我给指数级暴力写了一个分段,结果在本来指数级会爆掉的数据里,却调用了这个暴力,导致我白白丢掉了许多分数)
-
注意各种单调性的优化,以及结合打表优化 (S-D2,T2 可以用单调性条件优化掉对
k 的枚举,从而 64 分,而再打表寻找规律,就可以 88 分了(至于高精度什么的随便吧)) -
有将题目抽象概括,并转换为经典模型的意识 (J,T3,将题目(的部分分)用抽象形式概括、并简要思考后,可以发现就是一个完全背包,然后题目的思路就打开了)
-
注意结合程序意义,适当调整数组大小 (J,T4,我考场的程序会将某个点重复入队(疑似最多 2 次),因此队列大小不只
n ,但我只开了n ,导致痛失 10 分)