HNOI2019 游记
HNOI2019 游记
Day 0
其实考前几天,心里还是挺慌的。结果最后 Day 0 的时候,因为种种原因反而释然了。也许是觉得,在这一步退役,也没有什么好害怕的吧。
OI 本身就是一项偶然性太大的竞赛。也许在你遗憾失利的时候,还有更多比你强的选手倒在了省选前。
Day 1
拿到题之后,跳了计算几何与字符串,先开了相对擅长的计数。仔细分析了一下性质,发现大概是一个树的遍历的方案数。如果带修的话,因为修改的点数不多,大概可以暴力除掉原来的贡献,在乘上新的贡献就行了。
当时觉得乘上新的贡献的时候,要重新计算子树的大小,觉得细节有点多……当时决定,先写个 \(O(nm)\) 的暴力,最后看情况再改成 \(O(n \log n)\) 。大概 \(9\) 点的时候开始写代码,结果活生生调到了 \(11\) 点左右的时候才把暴力调出来……感觉再写下去会出事,赶紧扔了去看别的题。
回头看 T2,想了好一会怎么 \(\text{SAM}\) ,结果发现直接 \(\text{KMP}\) 就完事了……忽然意识到可能 \(\text{Undo}\) 一个 \(\text{Undo}\) 操作,还要建操作树,在操作树上跑 \(\text{KMP}\) 。写完之后,思考了一番满分做法,似乎可以把长度和字符视作一个二元组,对这个二元组再在操作树上跑 \(\text{KMP}\) ,特殊处理掉第一段,忽然觉得能做了,但是细节一大把……感觉不太能写了,于是赶紧扔了看 T1。
T1 上来写了个 \(O(n^6)\) ,想了一下后续,感觉都不是能在短时间内能拿分的玩意儿,拿了 \(20pts\) 直接溜了。
大概这个时候还剩下不到 \(1h\) ,手里还有 T2 和 T3 的正解,都不太能写。这个时候先尝试着写了分更多的 T2 ,仔细想了很久细节怎么处理,结果才写了没多久就觉得写不下去了……又看到了 T3。
冷静分析了一下 T3 更好写的写法,忽然发现,一条线段对应的子树大小,就是它的右端点 - 左端点 - 1。然后乘除组合数的时候,大部分的阶乘和阶乘逆元都抵掉了,最后只剩下乘两个数,除两个数。但是当修改连上了 \(n\) 号点和某个点的时候,还需要特判,最后的时候这个特判愣是没调过,就让它跑暴力去了……
出来的时候还觉得自己有 \(20 + 50 + rand(65,100)\) ,结果出来就发现 \(\text{KMP}\) 复杂度是均摊的……自己那个做法只有 \(20pts\) ,而那个所谓的正解也只能过没有 \(2\) 操作的点。想要通过总串长较小的点,还需要写个自动机一样的东西,这个东西拖到那个假做法上,字符集会很大,一下子不太会怎么搞。
结果最后出分 \(20 + 70 + 60 = 150\) 。T2 数据水的不行……真是服气……T3 \(\text{WA}\) 了俩\(\text{RE}\) 了一个,剩下的全 \(\text{TLE}\) 了。\(\text{WA}\) 是一个地方变量名打错了…… \(\text{RE}\) 是我直接把一个 \(\texttt{std :: deque}\) 赋值给另一个,结果好像不太能这么干?要先 \(\texttt{clear}\) 掉被赋值的哪一个,否则会出现随机 \(\text{RE}\) 。\(\text{TLE}\) 似乎就是被卡了……
Day 1 的分虽然还能看,但是打得很咸鱼……
Day 2
昨天仨取模,结果今天还有俩……行吧其实这种题还是挺适合我的。要是三个数据结构怕不是会被打爆……
先看了一下 T1,给我感觉是个签到,但我咋暴力都想了好久……写了一个记忆化搜索,开始还以为这个是 \(O(nm)\) 的,说不定 \(\texttt{bitset}\) 一发就过去了,结果仔细分析发现是 \(O(m^2)\) 的,这咋 \(\texttt{bitset}\) 啊……感觉不太对,先扔了看 T2。
T2 前 \(20\) 应该是暴力,后面保证了 \(k\) 是 \(2\) 的次幂,又满足 \(k | p - 1\) ,看上去比较循环卷积。仔细想了想,感觉可以写个矩乘 + \(\text{NTT}\) ,这样就有 \(60\) 了。后面都没保证 \(k\) 是 \(2\) 的次幂,这还能循环卷积?一脸被卡科技的感觉,于是去看 T3。
T3 盯着样例解释看了一会,不知道怎么就想到一个 \(O(nm)\) 的贪心,感性一波感觉正确性没啥问题,于是直接开写了。拍也没拍,不知道自己拿来的自信……
回头写 T2,忽然发现模数没给,并不知道原根怎么求……跟着感觉乱写了一个求原根,仔细想了想好像没啥问题?写完了矩乘 + NTT,忽然发现这个裸暴力我好像……不会写!想了好久,好像只会 \(O(L^2)\) ……当时不知道怎么回事,觉得这个裸暴力可能要写任意模数NTT……自己认为的签到题还只有裸暴力分,于是回头看 T1。
整个想 T1 的过程里,脑袋里全是 \(\texttt{bitset}\) ……根本没往优化建边的思路想。考试结束前尝试用各种数据来卡这个记忆化搜索,怎么卡也卡不掉……有点蒙……
估分 \(30 + 40 + 50 = 120\) ,出来问了一圈感觉好像不差,就是这个 T2 的裸暴力没写出来有点可惜……直接乘个组合数就行了,也不知道考场上脑袋抽了什么风……
结果最后出来 \(0 + 40 + 50 = 90\) 。我怎么又双叒叕挂分了……仔细想了想发现这个记忆化搜索好像是错的,这样有概率把 YES
判成 NO
……必须从合法状态开始 \(\texttt{bfs}\) 才是对的。
感觉自己这两天考得实在很咸鱼……不过好像很多人都挂了分,所以分都不怎么高。最后勉强混了个 A 队,看了圈 A 队名单,感觉自己 NOI 真的要 A 队垫底了……
Day \(\infty\)
又是一场考得比较崩的比赛,仔细回想起来,真的丢了太多不该丢的分。若不是数据水救了我一命,就只能排到 B 队中游了。Day1T3,Day2T1 和 Day2T2 都有不该丢的分,单单是写挂的分加起来也有 \(70\) 分了……究其原因,一方面自己写代码的时候,缺乏检查的过程,没有仔细分析正确性;另一方面,自己对于某些细节比较多的题,常常没有想清楚一些细节就直接开始写,导致花费了太多时间,甚至最后没能通过。像这个 Day1T3,如果我一上来仔细想想怎么写更好写,绝对是可以在 \(1.5h\) 以内写完的。
接下来的三个月,还有一些算法窟窿需要补,考试的准确率还需要训练,代码能力还需要提高,还有太多的事情要做……
NOI 不再容许我犯这么多的低级错误了,加油吧!