非常荣幸能够代表中国参加第35届国际信息学奥林匹克竞赛(IOI 2023)。受疫情影响,前三年的比赛中国队都采用了线上参赛的形式,并且都取得了非常耀眼的成绩,今年得以恢复线下参赛,我们在欣喜之余也免不了颇有压力。

第一天比赛,因为匈牙利距中国有六个小时的时差,加上平时没有晚起的习惯,我凌晨两点就醒了,对应中国时间的上午八点。半梦半醒地躺到早上七点,就起床准备比赛了。

比赛开始。虽然昨晚休息得不太好,但此时感觉精神状态还不错。先读完三道题,感觉closing应该是类似贪心的算法;longesttrip的答案应该大概率是哈密顿路;soccer的答案形状大概是凸的。

先做closing,每个点显然只有“不选、选近的、选远的”三种选择,一开始没想清楚节点之间的限制浪费了十几分钟,但是很快意识到了应该分X、Y选择区域有交无交两种情况,然后就可以让每个点的选择变为独立的。在1小时的时候写完了O(n^2)的暴力并获得了83分,然后用树状数组把它优化到了O(n log n),写这个做法的时候代码出错了几次花掉了十几分钟,在1小时40分钟的时候才过掉这题。此时感觉有些疲劳,只能多去洗脸来让自己清醒一些。

然后做soccer,一开始以为答案只是如下形式:一个中心点确定的一行一列,分成的四部分是四个阶梯的形状。写了暴力之后无论如何都得不到分,只好写了个对拍,终于发现结论假了。赶紧写了个搜索,在2小时50分钟的时候才拿到了35.5分。赶紧去做longesttrip。

对于longesttrip,结论的推导比较顺利,一开始的做法是维护两个完全图、一条链或一个环,加点的复杂度是O(log n)的。在大约3个半小时的时候写完了这个做法,得到了70分。然后发现可以维护两条链,这样加点可以做到O(1),至少能得85分。在写这个做法的时候遇到了一个很离谱的问题,我为了方便使用写了两个同名且同功能的函数,一个以vector<int>为参数,另一个以int为参数,调用vector<int>的版本,但调用的时候直接写了f({x}),导致它调用到了自己,从而TLE。偏偏本地随机的数据测不到这种情况,我花了大概20分钟才查出这个错。

最后半小时,我选择去做T3,但是并没有得到分。

出来发现大家都AK了,而我只有220.5,是18名,心里比较失落。总结这一场比赛,策略和心态都有问题,也因为前一晚休息不佳而影响了一些精神状态。中间感觉十分疲劳,思考速度和代码速度都远不如平常。

但是与其失落,不如好好调整第二场的状态。

第二场比赛,因为中间有一天的休息时间,对时差有一定的适应,晚上休息得还不错。还是先读题,beechtree没有头绪,看起来需要推结论;overtaking看起来像是处理分段函数;robot是造计算机,但是对怎么把bfs写成题目给定的形式没太有头绪。

鉴于第一天的T1是签到题,我还是先去做T1 beechtree,给自己留了一个半小时的时间限额。

我推出了一些结论,例如把儿子的颜色写成集合,所有点的集合需要是包含关系;例如父亲的集合要包含儿子,但是这些条件都只是必要的,并不充分。我尝试把这个结论再往下推几层,但是涉及到儿子套儿子,感觉太过复杂,就放弃了。

大约1小时10分钟的时候,beechtree还是一点进展都没有。于是我只好转而去做overtaking。

思考了几分钟,我发现这道题才是签到题。因为快车不会对慢车造成影响,所以可以忽略所有比X快的车,然后X也不会影响到其它车了。故可以把其它车的路线预处理出来,找到第一个X与某辆车重合的时刻,这些关键点只有O(nm)个,可以用从后往前推的方式处理这些点的答案。至于找这个时刻,用一个二分就可以了。

我先写了每次查询O(m log n)模拟的代码,用这个查出了一些预处理中写错的地方。然后把它改成了O(nm log m + Q log m) 的,并且很快通过了。这道题一共耗时40分钟,现在的时间是1小时50分钟。

到现在为止,感觉状态比第一天提升不少。

然后看robot,这道题主要的问题是机器人的行动只能用自己和周围一共5个格子的状态决定,而不能记忆任何东西。这时候如果想把算法明确划分为若干阶段,在格子上记录的信息就会增加很多。

为了后面写代码方便,我先尝试写了第一个subtask。然后开始思考正解。

找最短路必须用bfs,而bfs本来就是一个一个阶段进行的。在一个阶段中,我需要访问所有bfs树的叶子,并向外扩充一轮。而访问叶子可以让我想到dfs。于是大致确定了算法过程:bfs,但每一轮用dfs更新这棵bfs树。

在dfs中,我需要记录每个点当前dfs到哪个儿子。因此得到了如下过程:用2,3,4,5指向bfs树的父亲;6,7,8,9表示当前点在栈中,且表示它指向哪个儿子。这样就可以完全用一个点周围的信息确定当前在dfs中的位置了。

有了这个思路,我先写了subtask 3来验证向下dfs的过程,然后写了完整代码得到了65分。此时的时间是3小时50分钟。

因为此时beechtree还几乎没有分,所以我赶紧去做beechtree。

经过半个小时没有收获的推导后,我决定补一点暴力。T3还有15分的暴力没写,但是T1零散的暴力更多,于是我开始写T1的暴力。最后半小时T1的得分是35。

这一场比赛,不管是状态还是策略都没有大的问题,但是T1没有推出来比较拉分。这场比赛把我的名次提到了第8名。

这个最终名次虽然并不符合我的预期,但这次IOI之旅我还是有很多的收获。

在IOI见到很多外国选手,他们给我的最大印象就是“会玩”。这里的“会”是指可以玩得很开心,完全放松身心,但是又不耽误学业。他们玩的内容不止于游戏,还有对于唱歌、跳舞、运动(例如球类、跑步、游泳)都有极大的热情,很喜欢参与此类活动并且投入其中。例如比赛后的文化之夜,主办方为我们安排了跳舞的活动,大半的选手参与其中,但我总会产生一些放不开的感觉。再例如我认识了一位德国选手,他在空闲时会去旁边的运动场跑步、踢球、游泳等。同时,他们对自己的人生也有着很好的规划。我认识了一个15岁的俄罗斯选手,他问我们的问题居然是“你们大学毕业后准备干什么”。

我意识到,我们从小学至今的学习,是有一个固定的“最优化目标”的,例如分数。但是以后的人生,我要优化的不止于分数,还有身体素质、读书量、人际关系等等,甚至在将来的研究中,可能没有一个用来量化成果的“分数”。这对我已经习惯优化分数的算法来讲是一个不小的考验。这也是我在将来要面对的挑战,我非常期待。

最后,非常感谢领队老师们。匈牙利有很多让我们感到不适应的因素,老师们都尽一切可能为我们排解,例如给我们准备了药品、口罩等。我们去往匈牙利经历了一次转机,一共有26个小时的奔波,凌晨十二点才到达指定的酒店。在这种旅途劳累下,老师们在到达的第一天还熬夜到凌晨为我们翻译题面,坚持不出一点儿错误。第二场比赛前更是熬夜到天蒙蒙亮,才最终确定题面翻译的细节。

同时非常感谢队友们。我们在国外都尽可能地互相帮助,排解比赛的不利因素,在我第一天失利的情况下队友们给予我很多鼓励。

我是在国家队选拔6进4的答辩环节,从第五名晋至第四名,最终进入国家队的。在我第一天比赛失利后,出现了一些质疑的声音,例如 “是否让原本第四名的同学上场会取得更好的成绩?”在这些声音出现后,我同时也看到了很多同学为我声援、辩论,这些讨论让我非常感动甚至落泪。对这些同学,我由衷地感谢你们。

我尊重这些不和谐的声音。能进入到六选四的同学都十分优秀,但是我能进入国家队是CCF坚持公正的结果,也是我用自己的努力换来的结果。诚然Day1比赛发挥失常,但是能及时在Day2调整好状态和策略也是我千百个日夜训练得到的果实。我正视任何缺点,但是也不惧怕任何挑战和挫折,对自己怀有绝对的自信。

最后的最后,再一次感谢CCF,感谢所有的老师,队友,所有给我支持的家人、同学、朋友。我一定不辜负大家的期望,继续向更好的自己努力前进,并且我也相信,“向坚信的方向,定能驱动它——未来!”