关于一场比赛
【注意】本篇文章同步在 博客园 上发布。
概况
首先,先允许我说一下这次比赛的全过程。首先 \(\texttt{14:00}\) 开赛,\(\texttt{18:00}\) 完赛,这些都是基本信息。然后这次题目配置属于两绿两蓝,这也是不用多说的。\(\texttt{14:00}\) 开赛后自然要先做第一题,上去一看发现是自己栽了很多跟头的数位 DP,顿时冷汗都下来了,但随后告诉自己一步一步来总能解决的 (因为我只会递推不会递归)。一开始,我给 DFS 设置了 \(4\) 个状态,就像老师给的模板一样,后来我又设了 \(5\) 个,\(6\) 个。。。但是,最后我只设了 \(3\) 个,因为那时我已经明白了这题代码的具体思路了。但是,时间不等人,磕磕绊绊已经来到了 \(\texttt{14:40}\) 左右。随后,磕磕绊绊写了 \(\texttt{25}\) 分钟左右代码,又调了差不多 \(\texttt{10}\) 分钟,最后终于写完了。不曾想,鬼使神差的我尝试连续打出了几十个 \(5\) 和几十个 \(6\),本来只是想用大数据玩一玩,但是没想到被我完成了负数!当时心里哇凉哇凉的,这得查到什么时候?突然,灵光一现,我里面取模了但是我外面并没有取模。很快写好标准取模代码 x=(x%p+p)%p,最后一试,终于输出正数了。我谨慎起来,试了好几个数据,都没有什么问题,才放心大胆下后一题。
随后,直接把第 \(2,3,4\) 题全看了。直觉告诉我第 \(2\) 题是树形 DP,第 \(3\) 题显然的期望(题目都告诉你了),第 \(4\) 题感觉又像退火,又像状压(估计是被最近几天训练影响了)。所以,显然,应该按照题目序号升序做题。于是开始思考第 \(2\) 题。第 \(2\) 题看完了之后暂时没有什么思路,于是着手分析样例。当我看到有 \(2\) 个需要的输出时,瞬间有了可以先去把第一个输出打出来再去考虑第二个输出(当然,这也酿成了悲剧,痛失 \(\texttt{5pts}\),因为紧跟着输出数据下一行就是什么什么情况输出 \(0\),当然不排除我欠考虑)。第一个输出发现非常简单,就是 CSP-J 上的初赛题,按照题目要求以及边种类乘乘就行了,\(5\) 分钟写完代码,考虑第 \(2\) 问。一开始没什么头绪,于是从根节点依次往下通过草稿纸和墨水考虑,后来在思考的过程中突然想到自己之前总结的一句话,就是如果状态不够,维度来凑。突然有了想法,准备践行。既然 \(dp_u\) 不够,那么 \(dp_{u,x}\) 来凑。瞬间想到了解法,此时 \(\texttt{15:50}\)。设 \(x\in [1,R]\),那实际上对于 \(dp_{u,x}\) 而言它不就是指第 \(u\) 节点且点权为 \(x\) 的最小子树点权和吗?它不就是由满足题目给定的条件的子节点的 \(dp_{v,y}\) 转移过来的吗?于是,很快打出了最初代码。结果调了半天没调出来(此处省略一万字),长话短说,原本的代码几点问题:
- 部分数组赋值问题。(关键是真的查不出来)
 - 循环嵌套的先后问题。(例如,对于子节点的遍历要放在遍历 \(x\) 里面,遍历 \(y\) 外面)
 - 解决完嵌套问题后的一系列遗留问题。(真的,对于这种情况真的建议重新写完整代码)
 
在打完原始代码的过程中就发现时间复杂度为 \(O(nR^2)\),显然会超时(但是数据太水了,赛后提交了一下竟然也能过)弄完了后,拼命想优化没想出来,于是转手准备开第 \(3,4\) 题。但是,中间遇到了突发情况:我的头突然毫无预兆地开始疼了!什么情况!What happened? 这两道题就不多说了,没写出来。本来想第 \(3\) 题能推一下,但是头实在太疼了转不动脑子,就算了准备第 \(4\) 题拿部分分。对于一些情况根本不打算证明,样例说什么就是什么最后也是打完了 \(3\) 个样例都过了最后落得了一个 \(\texttt{0pts}\) 的下场。
时间 \(\texttt{17:30}\) 左右,转头思考第 \(2\) 题。DP 的优化都是从状态转移入手的,所以应该从状态转移上做文章。果不其然。不知道是大脑停摆了一会儿休息好了还是怎么的,注意力提升了,竟然注意到了对于状态转移
而言,最小值的取值只与 \(dp_{v,y}\) 有关。等等,它形如 \(dp_{u,x}\)?
于是,真正的理论解法就显而易见了。我们不妨在进行 \(dp_{u,x}\) 状态转移的时候,顺手把最小值记录一下,然后,就完事了。但是,这里有个比较坑的点,就是有个地方也许会出现不能直接使用最小值的情况,例如 \(x=y\) 且 \(op=0\) 的时候,所以我们还需要记录一下次小值。
当我在 \(\texttt{17:43}\) 发现这个解法,开始临危不乱地写。终于,在 \(\texttt{17:59}\)(并没有夸张)的时候,我将我更改过后的代码交了上去。虽然更改就花了 \(2\) 分钟,但是调花了整整 \(13\) 分钟。
喜提 rk3.
总结
说了这么多,那得总结一下。刚刚的描述中就有蛛丝马迹,有些是新的注意点,有些则是老生常谈的东西了。
- \(\text{\bf{考虑全面。}}\)这就要求我们在进行讨论的时候要考虑所有情况,而不是盲目地进行代码编写。永远记住,我们追求的是质量,是分数,而不是时间和速度。
 - \(\text{\bf{不要轻视样例的弱小。}}\) 也许,你知道样例是很仁慈的,但是为了追求速度,追求题目完成率,最后却并没有对其弱小进行“打脸”。在做题的过程中,我们不妨自己弄点自己的数据(毕竟自己的人用着放心),例如第一题,这样就能查出问题。
 - \(\text{\bf{写代码过程中不要放弃任何一个问题或潜在问题。}}\)也许你会说慢点就没思路了,但是仍然可以记录思路到草稿纸上,就算写成作文,也是比为了不忘记这个思路而放弃一些细节处理最终功亏一篑要强。任何说理都要讲道理,就算你用了大量举例论证,这也算。
 - \(\text{\bf{最重要的还是将一个知识点想明白了。}}\)做题过程中会因为知识点不熟悉或者说练得不够多而放慢速度。这是不可取的,也是可以避免的。所以,从现在开始,不懂就弄懂,没学过的就学透,扎扎实实一步一步前进。不然,要么看硬实力(只有一点点),要么看命。
 
                    
                
                
            
        
浙公网安备 33010602011771号