前言
这是一篇关于 OI 考试的一些策略、方法,里面会讲一些笔者认知内重要的东西。对于 OI 考试来说,光是有"一身武功"要想打出好成绩可能还远远不够,我们需要通过一些合适的技巧让其有"用武之地"。所以在此我准备讲一讲比较合理且普适的策略方法。此篇文章的适用范围限于 OI 赛制,也就是针对 CSP、NOIP 以及 WC、省选之类的比赛。
引言
在接下来的内容中,笔者将分为四个方面总结考试的方法思路,其中会着重分析"做题策略"和"临场应变"两部分,本文可能有的思想观念有错误,这里欢迎大家交流讨论并指出错误,笔者一定虚心受教。
时间规划
在最开始我想先讲一下规划方面的东西,因为这个东西是最根本的。"凡事预则立,不预则废",一个有效的规划能让你在未来一段时间的里行为有目的、有方向,不会迷失在繁杂喧嚣尘世之中。时间规划能让我们的时间得到更充分、高效的利用,让我们在竞争中掌握一定优势。这个时代人们比拼的是效率,很多东西都和效率二字挂钩,我们只有尽可能提升自身效率才能更好的发展、成长。而时间规划有助于我们提升效率,故其重要性不言而喻。
做规划前首先要清楚自己要干一个什么事?比如这里我们的目的是考试,并打出自己真正的实力。知道了目的后我们就需要思考达到目的的方法。首先我们是不是应该先去确定我们的开题顺序啊?那么我们肯定就要先去花时间读题,再结合自身实际情况决定开题顺序。考虑读题并不是单纯的读题,那仅仅只是第一步。在了解题目大意后我们需要进行一个最基本的思考,就是这道题大概考察什么东西?贪心?dp?ds?串串?网络流?\(\dots\) 这就需要我们有一定的判断能力,这是可以练习并且是我认为需要练习的。你对一道题的评估越准确,你制定的开题策略就会越适合自己,并且在后续思考的时候也能少走一些弯路。
开题顺序无需多言,一定是先做对自己来说较为简单的题。读题的时间建议在 20 分钟到 30 分钟之间,这样能保证对每道题都有初步的想法,接下来就需要合理分配做每道题的时间,这里并不要求你能做出来,但是你需要清楚怎么样的安排才能让自己的得分最大化。以四道题的比赛为例,前面两道题我们可以每道题给 40 分钟的时间,后面的题每道留差不多一个半小时,但是我们往往还会在调试上花费不少时间,为了避免一些不必要的问题,我们可能在写代码前会花更多的时间去做一些收益更高的事情,例如验证代码正确性,构造特殊数据之类,后面会详细介绍,在此不展开。所以为了均衡时间,可能前面的题要控制在一道题一个小时,然后你才能有时间去思考后面的题。(注意这里的前面后面并不是指的题目顺序,而是你钦定的开题顺序。)然后在考试的最后半个小时尽量不要再去开新题,如果前面花的时间太多也不管了,最后的时间一定要回去检查代码,验证正确性,这里不仅是检查正解,拼的部分分也是要检查的。
当然你也不一定非要在最后检查,我个人的习惯就是做完一道题就先检查一下有没有 corner case 没有考虑,以及文件输入输出之类的东西。然后在做完两道题的时候认真检查前两道,最后留 10 分钟再检查一次。具体怎么安排可以根据自己的习惯,当然在前期的训练中你也可以尝试不同的风格,找到自己适配的模式。
做题策略
这里的讲解大致按照逻辑顺序。其实本来准备单开一篇博客写这玩意的,但是后来觉得没必要。
首先你在最开始是已经读过题并且进行了微量的思考的,在正式开始做这道题后,你要先再读几次题,读题的时候要慢,注意不要漏掉关键的信息。特别是别人标粗、加点、带下划线的地方,以及一些括号,或是对某的东西的解释说明,这些都要多想。最后,读完题面一定要先去看时限空限,再去看数据范围,以及给了什么部分分。一般情况下部分分都有一定提示的作用,所以这里建议可以从部分分入手去思考一道题,然后再去想怎么扩展到更一般的情况。关于如何思考并想出正解在此不多赘述,我认为这是平时刷题该考虑的问题。简单来说就是去寻找特殊的性质,或者从特殊的情况入手思考做法,然后在根据已有的东西去加强,思考自己需要求什么,然后去选择适合的算法去做。
想好了一个算法(哪怕它不是正解)后我们需要验证正确性,你可以尝试换一种思路看看能不能行得通,或者沿着之前的思路历程重新推理一遍,在思维复盘的过程中,如果发现有地方不同不要盲目否定哪一次是错的,而是要更加谨慎,把有问题的地方想清楚。认为逻辑没问题后我们不要沾沾自喜,而是还要去思考我们选用的算法是否合理?正确性、复杂度有无保证?最直接的解决方式就是自己构造样例,而不是依赖别人给的"大样例"。怎么去构造数据呢?我们可以从算法的特性去入手,比如一个题要用到 KMP 算法我们构造全 a 的字符串之类的,意思大家应该都能明白,总结就是要考虑算法的最劣复杂度有关的问题,以及一些特殊的数据下该做法会不会有漏洞。还有就是可以从题目本身的特点去构造数据,比如给了一棵树我们可以构造菊花图、一条链、蒲公英之类的,给了数列我们去构造全相等的、等差等比数列、有单调性的数列等等。注意这里的验证全部是在写代码之前应该做好的事情。
在做完上述的事情后,你又需要做一次选择,就是说你要不要去写代码?这个问题的答案取决于考试的实际情况。比如一个题你想到了正解,但是自己估计可能需要比较长的时间去写加调试,这个时候你可以先放一下,去看后面的题,如果后面的题可以做就先做,做完再回来写。那如果你对后面的题没太多想法你就可以老老实实先写完这道题再看后面还能不能拼一点部分分。那如果你暂时没想到正解呢?先不慌,如果这个部分分大于 50pts 并且写起来容易那我觉得你可以优先写这个,有时写完说不定就能想到正解,如果没想到你就可以先正常去做后面的题,如果之后有时间回过头还可以再想想正解或者更高一档的分。
最后才是写代码。写代码前可以先想一下自己要实现一个什么玩意,需要用一些什么变量、数组?如果记不住可以在草稿纸上写一写。你甚至可以写一下这个代码的流程,先实现什么,再实现什么?当你已经想得很透彻的时候就可以开始了,拿出你单身十几年的手速,速战速决!
临场应变
在这个内容下我想讲一些面对一些情况的处理方式,虽然但是,这一切都只是纸上谈兵,真的遇到的时候最关键的还是需要有冷静的大脑。
最基础的比如设备有故障,或者键盘垃圾等非常影响自身效率的东西建议速速举手告诉老师申请换设备,不然你就会难受一场并且容易心态爆炸。如果周围有那种 nc 喜欢说话的小屁孩也建议举手告诉老师,让老师制裁一下这种出生,这种人被制裁后你自己说不定心情还会变得更好。如果不小心把电脑整蓝屏、关机了也不必慌张,因为就算代码丢失了你也能很快再写出来,要相信自己一定能做到,要有信念,意志要坚定。
然后最主要的其实还是调试代码的问题。这个是个大问题,如果处理得好可能并不会影响什么,甚至可能都不会发生,但是大多数人往往不善于处理这类问题,并且在考场上花费大量时间死磕一道题最后螺旋爆炸。注意这并不是小问题,这是能力与心态的考验,我认为在某些方面其难度不低于想出这个题。调试代码不仅是脑力活,更是体力活,接下来我会着重讲如何处理这类问题。
最开始我们可以先静态查错,建议从最根本的东西开始检查,比如数组大小、数据类型、取模、初值、多测清空等等,然后可以按代码运行的顺序在脑中边模拟边检查。注意 if 语句有的地方大括号不能省略,有的地方改用逗号还是分号。注意有没有语句的实现顺序有误,或者哪里笔误把变量用混了。一些变量的初值有没有考虑到不同的情况,甚至看看会不会有 UB。特别要注意全局变量和函数变量有没有搞混,以及循环枚举的东西是什么,范围是什么?
静态查错是比较快的,可以先看了两轮。如果还是有问题就不建议继续干想了,这时我们去输出一些比较重要的参数去定位哪里出现了问题。考虑到之前验证算法的时候我们构造很多神秘小样例,这里就可以派上用场。如果只用下发的大样例,那就有你调的了,说不定调上个半场一场的。
然后如果说你在使出浑身解数后还是不能调出来,并且已经花费不少时间了,应该怎么办呢?当调了这么久后,我们的心态肯定或多或少会受到影响,所以我们首先需要调整心态,我们可以尝试深呼吸、心理暗示等方法,建议还可以去上个厕所。等自己稳住心态后你就需要想了:到底是死磕这道题还是先去看后面的题呢?这里建议选择后者,你可以先假设自己已经过掉这道题,不管它正常去做后面的题,只是最后可以多留一些时间重新看看这道题,有没有可能是自己的做法假了但是前面没 hack 掉?或者还有 corner case 没有处理?但是无论如何,请你相信自己,你要有能够做出题的信心信念,才能有足够的动力支持你最后调出来。
最坏的情况就是出现身体不适之类的,这时我们更要稳住心态。虽然这种事情会对我们的发挥有一定的影响,但是这些东西带来的副作用并没有我们想象中的那么大,就像参加高考前一天失眠,第二天也不至于比平时低个几十分,就算有那估计也是因为心里觉得自己不会发挥好,心理暗示导致行为意识,最后决定结果。所以在遇到这种状况后我们要思考我现在是否有能力继续考试?我要坚持一会吗?又或者就此放弃?建议是以自己身体为主,毕竟"留得青山在,不怕没柴烧"。
赛后总结
赛后建议估分写总结,思考自己这场比赛的得失。是否达到自己的理想分数?有没有打满自己的上限?哪里还可以做得更好?哪里做得好需要继续坚持?在后续的训练比赛中我们就要汲取教训,注意自己容易犯错的地方,多留个心眼。哪怕就算是退役了我们也要理性看待,要明白 OI 陪伴了我们的青春,但人生的路还很长。"路漫漫其修远兮",只有保持一颗积极乐观的心才能砥砺前行,哪怕达不到自己的目标,也不要给自己留下遗憾。但是要拥有一颗积极乐观的心又何谈容易呢?但好事多磨,只有当自己经历了很多事后才能对时间事物有更深刻的体会。
最后
最后笔者也祝大家的 OI 之路一路繁花似锦、前途璀璨,面对成功有真心实意的感恩,面对失败有一笑而过的洒脱。希望这篇文章能对每一位读者有所帮助。如有不同的想法与见解随时欢迎交流!