NOIp 2025 游记
1. 前言
CSP 之后马上迎来期中考试,第一天考的语文、历史爆炸了,剩下的都还行。文科在基础知识薄弱的基础上,是永远不可信赖的。想要学好文科,可能只能慢慢地补,因为文科的知识成体系,需要人融会贯通,甚至要在生活中去体验、感受,达到知行合一,达到一种“道”的境界。而理科仅仅停留在“技”的层面,只要在一段时间内认真学,完全能掌握。
考试之后我就是这样反思的,然而过了几天我突然发现好像是因为第一天考试前 5 点钟被邻居吵醒了才导致第一天全面崩盘的。我似乎总是习惯给自己找理由,因为现场感觉这件事对考试的发挥并无太大影响。但是或许又有一定影响呢?有的时候,在对学科、对自己的认识和评估上,就像爱情一样扑朔迷离、难以捉摸。但是,勇气、坚守等品质就建立在这种不完美的认识上。所以,不完美才能让人具有人的特征、品质。
OI 也总是给我这种患得患失的感觉。有时我觉得自己能触碰到金牌的水平,比如 WC 2024、APIO 2025(若是 T3 调出来了就有前 50 名了),以及 VP 的 NOI 2020 和 2022。但是我又经常性地被打击,比如 NOIp 2024、NOI 2025 以及这次 NOIp。这可能也不是水平的波动,仅仅是 OI 题目随机因素大的特性。但是就是在这种给予希望又无情打击的状态下,我才能一步步地走到现在。如果 NOI 2025 我的目标不是冲金牌,或许我连银牌也得不到——赛后无数次觉得银牌也有极大的运气成分。如果不是在幻觉中成长,人便会停滞不前;而若是朝着幻觉的方向努力,某一时刻的幻觉也可能成为之后的现实。
但是说到底我还是内核不够稳定、对自身定位的认知不足。在上述论证中,一个内核稳定的人也并非没有幻觉,而是他的缥缈的幻觉转化为了切实可行、稳定的目的,这样前进的道路会更加顺利。我则是在文化课和 OI 中反复切换、在各种培训机构中摇摆不定,再加上 OI 竞争的环境和敏感的天性,终究做不到这一点。但是在 OI 这样内卷、竞争、每日模拟赛排名的氛围中,谁又能幸存呢?
还是记录一下期中考试后到 NOIp 之间的事情吧。期中考试后的那个周末彻底放松,周日下午去香山玩,本来没想登顶香炉峰的,但是爬到一半上头了于是拼尽全力爬到了香炉峰,看到了很震撼的夜景。结果下山的时候因为用手机看地图崴脚了,被我妈搀着,强忍着疼痛走了两公里,非常艰难。第二天睡醒时崴脚的问题加重了,去医院,要在家里待四周。还好正好是停课的时候,要不然事情就很麻烦了。
于是,到 NOIp 的三周只能在家待着了。很怀念那些可以打篮球、跑步、骑车的日子,家里太寂寞了。这期间大概就是在补题、学集合幂级数(还没学完)和打模拟赛。模拟赛只获得了一次 rk1,而且经常被学弟吊打,要保不住作为学长的尊严了。这期间经常有不会简单题,反而将希望寄托于 T4 并切掉的经历。甚至第二周周末的 CF 也是不会 D 题但是切了 G 题,虽然说那个 G 题也是很简单的题。切不掉简单题的经历终于让我承认,我的基础和考场的心态真的不太好。
最后三天复习了一下之前学过的很多模板,打了很多之前从来没打过的板子。NOIp 考前那天晚上我突然想,如果 NOIp 就是我的退役之战,那复习模板就好像是向陪伴我多年的算法一一告别。这是一种超越理性的机器、将人的感情寄托于物的人类特有的仪式感。
考前一天我非常浮躁,根本打不下去板子。洛谷的 OIer 们也非常浮躁,看到了好多考前焦虑的帖子。其实考前调整心态首先就别发帖子。有一次看到一个帖子问斜率优化是否能考,我评论说李超线段树可以平替斜率优化,有人说见过专门卡 log 的题。当时我还不以为意,完全没意识到 \(\mathcal O(n^2)\) 这种题的存在。关于板子,一直打到 18:30 终于打完了,要是再打下去就必定信息过载了。统计了一下大概是打了 39 个板子,比以往都多,而且很多基础的算法并没有打。
2. 赛时
考前一天 22:00 睡觉,可能到了 22:40 才睡着,一共睡了 8 个小时,但是早上起来并不是很精神。
拄着拐进入学校,感谢一位保安陪我走了很长一段距离,并给电梯刷卡。
开题。看 T1,最开始脑子就有点不清醒,分成了奇数和偶数两类讨论。后来终于发现可以分成任意多个 \(x+y\) 和恰好一个 \(x\),并枚举 \(x\) 的前缀即可。9 分钟写完。
看 T2。天哪,怎么 T2 题面这么长,还是计数题。仔细读题后,发现它无论如何都需要非常精细地讨论。看到 \(n\le 5000,\sum n \le 50000\) 的数据范围,这不就是我没想到的会卡 log 的数据范围吗?这道题的复杂程度严重打击了我的信心。我尝试找到判定条件,发现需要将两段数组排序,并找到一个 \(2a_{m-2x+1}>b_x>a_{m-2x+1}+a_{m-2x+2}\) 的点。而且我并没有完全想清楚这个判定条件的正确性。可能是考前做过类似的题,我很自然地思考 dp 对选择情况的计数,但是这条路是行不通的。这时我竟然没有思考其他做法,而是尝试证明这个判定条件是错的,从而证明整道题不可做。迫于时间的压力,我赶紧转向其他题。
看 T3。看起来好困难,甚至想不到一个能过的暴力。仔细思考后,我推测如果一个子树包含 \(0\),那么它一定是一段连续的区间;否则它相当于若干个随便填的数,本身不产生贡献。但是我发现我完全没有用到 \(m\) 的限制,如果我在 \(\mathcal O(n^2)\) 的时间内能完成这个 dp,那一定是这个做法假了。但是我发现我首先需要枚举从 \(0\) 开始产生最大值的那个区间,这样的复杂度就是 \(\mathcal O(n^3)\) 了。所以我并没有否定这个做法。
看 T4。因为 T2 和 T3 都不太会,而 T4 是我比较擅长的数据结构,我隐隐约约地感觉我必须切掉这道题。看到数据范围,竟然又是一道卡 log 题!\(nq=5 \times 10^7\),而且暴力分极少,感觉出题人将思考的空间压缩到极小,就像被出题人推到墙根处,无法喘息。我首先思考了一些朴素的做法,比如求出来所有区间的答案,转化为二维数点,但是所有区间的数量就已经难以接受了。还想到考虑将 \(i\) 的答案转移到 \(i+1\),但是答案是 \(\max\) 的形式,而集合删数再维护 \(\max\) 是很困难的。
我发现 \(q\) 比较小,于是可以先将区间长度离散化,这样预处理 \(i\) 对离散化区间 \(j\) 的答案是可以接受的,如果预处理出来了,之后就只需要一个 \(\mathcal O(n)-\mathcal O(1)\) RMQ 了。顺着想,考虑枚举左端点和离散化区间,发现右端点是变化的,无法精准覆盖。但是我发现,如果 \(l\) 到 \(r_1\) 的距离大于等于 \(r_1\) 到 \(r_2\) 的距离,只覆盖 \(l\) 到 \(r_1\) 覆盖两遍也就够了!想要满足这个条件,只需要将离散化数组加入 \(\mathcal O(\log n)\) 个数就行了!于是我便会了这道题的带 \(\log\) 做法,接下来只需要将 \(\log\) 去掉即可。
求区间最大值可以用 st 表,但是覆盖区间最大值该怎么做呢?st 表逆过程吗?这不对吧。而且复原的时候也需要 \(\mathcal O(n\log n)\) 的时间,无法接受。冷静思考后我发现,覆盖区间最大值也就相当于求区间最大值,而区间的长度还是相等的,于是单调队列即可解决。接下来考虑 RMQ 问题。因为这是在 \(n\) 个数组上同时查询,所以或许有比较好的做法。那如何才能利用同时查询的性质呢?考虑离线维护单调栈,那么查询的时候为避免二分,可以同时算贡献,从 \(l\) 处一直推到 \(r\) 处,只需要在每个位置上恰好更新需要更新的点即可。那么加入的时候将每个点的上一个位置排序就行了!这样只需要遍历前缀。而单调栈只需要删除,删除可以使用链表维护。好巧妙!——但是也好难写啊。
关于 T4 考场的做法,详见我的题解。
这时已经接近 10 点,我认为 T4 要给两个小时写,而如果先写的话很可能连 T2、T3 的暴力分都拿不到,于是我先回去看这两题。
T2 又进行了许多无意义的思考,我甚至现在已经忘了当时在思考什么了。最终我妥协了,打算拼暴力和特殊性质。想起考前 pyc 写的备考建议上说,如果完全不会一道题,也并不是 100 分和 0 分的差距,仍然可以拼暴力。这的确是对的,我考场也是靠着这种想法忍辱负重地拼了 52 分暴力。这时竟然已经 10:55,我放弃思考 B 性质的分数了,而是赶紧转向 T3。是啊,不会一道题的确只能差出 50 分的分差,但是过程中浪费的时间和丧失的信心又何止 50 分呢?
来到 T3,我赶紧把那个看上去就不太对的做法实现——当然我考场时还是需要强迫自己相信它是对的。它通过了前两个样例,却挂在了第三个样例上。我终于意识到这个思路假了。从 \(0\) 开始的子树内编号不一定是区间。这时我想到是否子树是一段区间加上一些不产生贡献的数这样的形态?这样 dp 再加一维即可。可是这时已经 11:10,我不可能再花更多的时间了,而且暴力也不太会,只好交上这份错解碰碰运气了。
回到 T4,我先仔细回忆了一遍之前想的做法,接下来写了一份暴力。暴力写得并不算快,但是确保了思路的正确性,是有必要的。接下来开始逐部分改成正解(求 \(ans\) 和 RMQ 两部分)。写暴力的时候意识到这道题卡空间,\(ans\) 数组存不下,如果用 int 和 char 存也几乎顶满了空间复杂度,很危险。我感到极度愤恨,认为出题人的素质很低。我发现可以强行分段,逐段去求。改第一部分的时候也加入了分段的代码。
大概在 12:00 左右,我突然意识到比赛只剩一个小时了,而我还差第一部分没写完、没开始调,第二部分完全没写——而第二部分又是非常难写。我回想起 APIO 2025,那场比赛就是在最后一小时冲 T3 的 26 分,某一时刻突然丧失信心、一败涂地。而这道题调出来与没调出又是 100 分与 0 分之差,命运仅仅决定于一念之间。现在这场比赛,我感到紧张不安,又有一种浮躁的恨意,还有对自己徘徊、希望渺茫的 OI 水平和 6 年 OI 生涯的感慨。
写完第一部分或许是 12:10 左右,接下来便是漫长的调试。这是我最痛苦、信心跌入谷底的时候。我感觉我的思维已经飘离题目本身了,而像是对代码进行逻辑判断,输出变量,看这些变量之间的关系是否满足。我甚至会产生误判和幻觉,前后不符合的变量像是幽灵,行踪不定,当我将所有位置都输出出来,想要捕捉它的真相时,它又转而相符合,好似愚弄我。不知为何,赵雷的《理想》突然在我脑中播放,我已经有一段时间没有听那首歌了。“又一个四季在轮回,而我一无所获的坐在街头”,思绪飘到整个 OI 生涯,发现这可能是我的退役之战了,感到十分悲凉。
终于,我发现我少写了一部分——我的思路需要正反做两遍,而我只写了一遍。如此低级的错误也能看出我写代码的时候已经无法集中注意力了。改完这个错误后,它还是没有通过样例。我面对代码的错误毫无头绪,只能将代码越来越改成像暴力的状态——删掉单调队列,改为暴力枚举;删掉分段,改为 \(L=1,R=n\)……但是代码的错误纹丝不动。
大概是 12:25,我转向对拍,在时间极紧张的情况下,这大概是最令人绝望的调试方式。使用 \(n \le 10,20\) 之类的小数据竟然拍不出来,只在 \(n=100\) 的时候才产生错误,这与测试样例也没有太大差别了。我发现,我求出来的 \(ans\) 数组竟然有很多位置没有被更新。抓住这个线索,我终于找到了代码的问题所在——一个位置不能产生贡献的时候,也可以获得别的位置的贡献,不应被 break 掉。终于在 12:40 的时候,我过掉了第 2、3 个样例。
第二部分的正解肯定没时间写了,我开始思考一些好写的替代。从大到小遍历并判断是否属于区间,虽然期望是 \(\mathcal O(1)\) 的,但是当区间长度很小时就会被卡掉。于是我索性直接写 \(\mathcal O(nq\log q)\) 的 st 表,看能不能过数据范围较小的部分分。测样例 6,发现跑了两秒多。但是,与省选如出一辙的是,我并没有开 O2,开 O2 后最后一个样例只跑了 1.5s!我竟然切了这道题!在 12:49,我交上了这份 3.5KB 的代码。
我赶紧回去看 T2,想要做特殊性质 B。但是这时脑子一片空白,完全无法集中思考。这大概并不是被喜悦冲昏了头脑,仅仅是一种劫后余生的不可思议。我还沉浸在调 T4 调崩溃的痛苦情绪中,对调出 T4 感到不真实,也无法重新回到现实世界中。
我想给四道题检查一下,这时我突然发现 T4 的其他样例还没测,于是我测试样例 7,发现竟然跑了 4s!我发现时间的瓶颈竟然在前面的 \(\mathcal O(nq)\) 正解中。我尝试调整分段的个数但无果。我想不出任何对这份代码的卡常技巧,只能无奈地放弃了挣扎,等待官方数据的审判。
出考场时的估分:\(100+52+[0,16]+[50,95]=[202,263]\)。
3. 赛后
问了一下 wz 的分,也是 250 左右,但他基本会 T2,而且 T3 也得了 40 分,看来 T2, T3 我真的失分了。cyx 切了 T2,T3 和 T4 都有 70 分以上,太强了。初三的两位学弟 ljh 和 jch 都基本切了 T2,太牛了。
如果这场的分数可以达到估分的上限的话,应该也只能在省内排 30 多名,与去年 NOIp 如出一辙。唉,一年的努力完全没发挥出来。时代在推移,选手在进步,而我这种行将就木的退役选手也只能被后浪拍打着退出时代的舞台了。
upd: \(100+48+16+65=229\),退役了。

浙公网安备 33010602011771号