CTSC2018 & APIO2018 颓废 + 打铁记

时间:2021-01-15 11:02:50

CTSC2018 & APIO2018 颓废 + 打铁记

CTSC

5 月 6 日

完美错过报道,到酒店领了房卡放完行李后直接奔向八十中拿胸牌、饭票和资料。试机时是九省联考的题,从来没做过,我也不打算做了,随便试了下键盘、打了个 \(A + B\) problem 就离开了机房;找到了学弟学妹带他们回酒店颓……

晚上定外卖,领队将密码条送来,一日无事。

5 月 7 日

上午 8:30 开始的考试推到了 9:06,好像不同考场开始时间还不一样?!

上来先看了看每道题,时限分别是 \(6\texttt{s}\)、\(4\texttt{s}\) 和 \(3\texttt{s}\),每道题都这么宽的时限?

T1 假面,看完题感觉信息比较多,整理了一下思路,发现它主要就是考对概率和期望的理解,因为我看到了血量上限是 \(100\) 这个条件,于是对于每个人维护一下每种血量的概率就完事了?想到这里没有细想,感觉可以 A(flag),就接着往下看。

T2 暴力写挂,怎么又是全国冬令营那种两棵树仅仅通过节点标号强行联系在一起的题啊?感觉完全不会什么比较优的算法,不过 \(n^2\) 暴力好像能过 \(45\) 分?(我会 \(O(1)\) 求 lca 233333,而且时限是 \(4\texttt{s}\) 233333)

T3 青蕈领主,数数题啊,我还不是很擅长呢……先打暴力吧……诶等等算一下怎么只有 \(10\) 分?\(T = 100\) 的小数据是要干嘛?

于是我先写了 T2 的 \(45\) 分暴力,很快跑过了所有样例,测一下极限数据 \(n = 12345\) 的情况也能毫无悬念地在 \(4\texttt{s}\) 内跑出。

接下来去写 T3 暴力,发现果然只有 \(10\) 分,当时并不知道怎么优化到 \(20\)。看看特殊性质,我发现我会 \(F(i, j) = j\) 的点,这个性质保证每个前缀的值域一定是一段连续区间,这样 \(O(n^2)\) dp 一下就好了。写完后跑一下发现怎么答案都是 \(2^{n-1}\)?我也没想为啥直接改成了快速幂,怕这个 dp 又写挂哪里导致丢分。

这个时候考试过去差不多一半,我开始写 T1。在回答每个结界技能时,我处理了一下前后缀的 dp 信息,然后需要卷积合并,具体来说就是处理 \(Pre(i, j)\) 表示前 \(i\) 个人剩下 \(j\) 个存活的概率,\(Suf(i, j)\) 就是后 \(i\) 个;那么对于某个人 \(i\) 算他被打中的概率就是求所有情况中他被打中且打中其他人中 \(0\) 个、\(1\) 个、\(2\) 个等等的概率,就能计算出来了。这里明显需要将 \(Pre(i-1, j)\) 和 \(Suf(i+1, j)\),\(j \in [0, K]\),进行卷积,我开始写了个暴力,然后发现复杂度是 \(O(C \cdot n^3)\) 的,运行了一下发现过不了,于是我将这个卷积改成 NTT,然后……更慢了……的确,这个 \(n = 200\) 的小卷积暴力就应该比 NTT 快。于是我改回暴力,在那里想了好久并没有想出优化的办法……

最后我检查程序的路径、文件名、文件读写的时候,突然发现 T3 暴力的优化方法——将 \(100\) 组询问放在枚举的内层跑,能剪掉很多情况。我在最后 \(10\) 分钟改好了暴力,过掉了第 \(2\) 个样例,然后平复心情,静候考试结(挂)束(完)。

出来后发现全世界都 A 了 T1……有好多大佬会做 T3 的 \(60\) 分,然后打表打到了 \(80\) 分……感觉自己已经完全凉凉了。当时并不知道自己 T3 是 \(15\) 还是 \(25\),所以估计自己在 \(130 \sim 140\) 之间。

这天是 LazyJazz 的生日,本来想去看头号玩家的,但是貌似电影院没有今天的合适时间的场,所以鸽了,听完讲题后一起吃了顿呷哺呷哺,回酒店颓……

酒店里研究了好久 T2,由于太菜还是不会写正解……(后来听说 \(85\) 分数据很水,把边权当成正的就可以直接树形 dp 水过)

5 月 8 日

上午听答辩,抢到了论文,感觉速度太快完全跟不上,也许以后补补?【评委还是一如既往地装成一幅很专业的样子

下午人工智能完全不听,校园完全不(需要)参观,待在酒店里颓(哎就当我在休息吧……调整状态以备下一天的考试)。

晚上学习三国杀……突然发现好有意思 23333333333

5 月 9 日

这次上午 8:30 准时开始比赛了。

(由于一些问题,这个问题在后面会提到,二试的题面没有公开,我简述一下题意)

T1,给你一些果汁,每种果汁最多可以用 \(l_i\) 升,美味度为 \(d_i\),每用一升将消耗 \(p_i\) 元;现有 \(q\) 组询问,每组询问给出 \((g_i, L_i)\),表示询问花至多 \(g_i\) 元至少喝 \(L_i\) 升能喝到的所有果汁的最小美味度的最大值是多少。

这个东西显然就是一个二分 + 贪心,首先二分答案 \(x\),那么就只能使用 \(d_i \ge x\) 的果汁,然后将这些果汁按照价格从小到大排序贪心选取 \(L_i\) 升即可。

这题看完了一眼想到做法(愚蠢的是我开始以为这么做就完了,忘记它是多组询问了……)

T2,给你一颗根节点为 \(0\) 的 trie,每个节点上有一个字符,表示 trie 上它到它父亲边上的字符,字符可以是数字、, 或者 ?,你需要将每个 ? 变成 , 或者数字,要求变之后

  • 串的字典序最小(串就是将 \(i\) 号节点上的字符放在第 \(i\) 位)
  • trie 上根到每个节点的路径所代表的串是一个合法的严格递增的正整数序列(就是由逗号隔开的一堆正整数)

细节太多我就不描述了……这题看看连暴力都难写啊!等等,暴力好像拿不到分?\(11^8\) 貌似爆炸了,而且复杂度还不止这个?果断弃疗。

T3,提交答案题,有 \(K\) 台机器要计算 \(n\) 个 \(A+B\) 问题,每个问题 \(u\) 有一个依赖问题 \(f\),需要这个依赖问题 \(f\) 解决后并将数据从 \(f\) 所在机器发送到 \(u\) 所在机器后 \(u\) 才能开始计算。给出第 \(i\) 个问题被第 \(j\) 台机器计算的时间 \(A_{i, j}\),以及第 \(i\) 台机器将数据传输到第 \(j\) 台机器的时间 \(R_{i, j}\)。并给出 \(op(op \in \{ 1, 2 \})\),若 \(op = 1\) 则最小化所有的计算时间总和加上传输时间总和,否则最小化最后一个问题计算完毕的时间。

看到题面里给了一个 simulator,不用自己手写了,感觉很可玩;再看看数据,前两个貌似可以暴力枚举,后面有一些 \(m\)(依赖关系数目)为 \(0\) 的点;还有依赖关系是几条链、分层图的点,貌似比较有趣啊,写完 T1 就来玩。

T1 我回去重新看了一下题面(因为我感觉不可能这么简单),发现我果然看错了……不慌不慌,这个题肯定是数据结构裸题,一定能想出来……先打暴力压压惊吧……暴力除了最后一个样例都过了。

过了一会真的想出来了(我还想过整体二分、把所有果汁按照 \(d_i\) 降序排列并离线的做法,事实上这些思路对想到正解有一定帮助),我们对 \(d_i\) 从大到小建主席树不就好了?二分答案后检测答案是否可行时在值域线段树上二分一下不就好了吗?

好的开始写正解,没花多长时间,测一下发现暴力能过的样例都过了,但是最后一个大样例错了一些地方,找了半天发现是一个乘法忘开 long long 了,改掉之后过了大样例;然后写了个对拍器和暴力对拍了几百组数据,这道题应该没问题了。

然后去玩 T3,我尝试将它的 simulator 输出到屏幕的东西输出到文件,发现用终端中重定向的符号 > 没有用,感觉很绝望;但是就在最关键的时刻我看到了一个叫 res.txt 的文件,里面包含一个整数,就是 simulator 运行出来的结果!希望重燃,我写了个暴力跑了几分钟把第一个点过了,发现是 2 3 3 3 ...。照这个速度是不可能跑出第二个点的……怎么办,为啥 simulator 这么慢?!

然后我写了一个模拟退火,但是由于无敌慢,后面的点也最多两三分的样子,大多数还只是一分……

折腾这么久没时间了……想不出送分点的特殊算法了,近乎绝望……(而且我不会写 simulator,可能当时已经神志不清了吧……)

绝望地走出考场,听说有人退火拿了 \(81\)?!醉了……

焦急等待成绩……

焦急等待结果……

诶工作人员来了!刷开了机房门!他进去了……然后把门带上了……

焦急等待成绩……

焦急等待结果……

诶 CCF 领导来了!刷开了机房门!他们进去了……然后把门带上了……

焦急等待成绩……

焦急等待结果……

诶贾老师出来了!他出来了……然后告诉我们今天下午不做评测……woc 浪费感情。

接下来去看面试。候选队英语不咋地,不过后面几个英语水平明显碾压前面的。这次好像是史上第一次评委用英文提问?英文很多啊。

诶听说有人程序丢了?!没讲评了?!没有颁奖典礼了?!处处传来“咕咕咕”的声音。

这口锅,有点大啊……

还没完,我的程序也被搞丢了,在只有一个舞蹈节目的闭幕式草草结束后有 \(85\) 个人被点名留下……

CCF 的决定是明天重考一次,考什么题“无可奉告”,“大家不用担心,我们不会亏待你们的”,“不用紧张,回去洗个澡早点睡,明天过来正常考试即可”。我也没啥好说的了,场上已经有人提出异议,但出这问题本身就没法解决……

晚上我教了一下两个学弟这天的 T1 怎么做,我也去北师大实验那边求得了“退火真传”,然后打一局三国杀,洗漱睡觉。

5 月 10 日

“今天要是考昨天原题我就……”(立了一个不好的 flag,最后装作无事发生)

到了考场,下发纸质题后我真的惊了!我确认一下是否有陷阱,然而这题真的和昨天一模一样!(当然 T2 题面进行了修改,T3 在题面末尾教你了如何给 simulator 添加运行权限)

机房里其他人早早开始敲起了代码……

我直接写 T1 正解,照着昨天的程序几乎没变地敲了下来……过了大样例我就不管了。然后去搞 T3,首先用上前一天学会的 2> 重定向,然后写退火,过掉了第一个点,然而发现 simulator 还是太慢,过不了第二个点,于是我下定决心自己写一个 simulator,\(op = 2\) 的情况调了好久……

写完 simulator,速度大幅提升,退火(要手动调参)得出了 \(1, 2, 6, 9, 10\) 的满分答案,一些点的部分分答案,然后再把 \(3, 4\) 的特殊数据写了,最后拼起来是 \(75\) 分。

我还是不明白怎么一个退火 \(81\) 分……

T2 我还是一看到就想吐,于是强上 \(11^8\) 暴力,听说不会全 T,但是最后还是写错了。

比赛后两个重考的学弟想先溜,我帮他们查了成绩,他们都 A 了 T1,昨天告诉他们做法是有用的。我还是一如既往地凉。

然后就这样我自己骑回了酒店,并完美错过了 APIO 的报道……


CTSC 非常凉凉,我痛定思痛,大概总结了一下这次比赛打不过别人的原因:

  • 一试的 T1 \(30\) 分输不起,这个题直接多项式除法一下就可以“逆”着 dp 回去了,完全没有超过我的知识和思维难度范围,这 \(30\) 分也导致了我最终没有拿到 Au。
  • 从一试的 T2 可以看出我获得部分分的能力非常低,大多数人能拿到的、NOIP 难度的分档我都没有拿到,当一棵树是链的时候,可以树形 dp,因为在链上无非就两种情况:要么在 \(1\) 同侧,那么深度较小的就是 lca,否则就是 \(1\) 的异侧,那么节点 \(1\) 就是 lca。这道题还有人用随机化乱搞过了,我认识的北师大实验的初三用随机化过掉了 \(90\) 分,他们乱搞能力太强了,相比之下我这方面能力就很差。
  • 同理二试的 T3 也反映出我乱搞能力、写部分分的能力差这一点。

我认为解决办法就是今后不仅要在模拟赛上多争取拿分,在改题的时候也要多下点功夫,不是改成 \(100\) 分就结束了,而是接着实现一些复杂度更高的或是种类不同的算法、以及部分分所用到的算法。


APIO

这一天还在继续,接下来好像就是休息、打三国杀、休息、定外卖……总之很颓。试了试 APIO 练习赛,感觉这个网站界面还挺友好。

5 月 11 日

今天复仇者联盟 3 上映,这是一个大喜的日子,早在 CTSC 报道之前 LazyJazz 就锁了 \(4\) 个座,在 7 号那天又多锁了两个座,上午听了听课,下午翘掉一波人全都去看复联。无论特效还是剧情都无敌震撼,为了避免剧透被打,并且这是比赛总结并不是电影交流,我就略过了。

下午吃饭、领密码条,一切照旧。

5 月 12 日

考试在 9:00 准时开始了。题目有各种语言的翻译,感觉还是挺友好的。

点开题面:“五福”、“小明”……?这是什么风格?

点开 T1,一眼看上去是一道数据结构送分题,题意就是:给出 \(n\) 个位置在数轴上的超市,第 \(i\) 个超市会在时刻 \(a_i\) 到时刻 \(b_i\) 在坐标 \(x_i\) 出现,超市种类为 \(type_i\);随后给出 \(q\) 组询问,每次询问在时刻 \(t_i\) 出现在位置 \(p_i\),求这个时刻所有种类的超市到 \(p_i\) 的距离最大是多少;种类 \(i\) 到 \(p_i\) 的距离定义为所有种类为 \(i\) 的超市到 \(p_i\) 的距离的最小值。

首先想到离线,然后就是支持插入、删除、询问最大的“某个种类到某个位置的距离”,感觉随便用个数据结构就能维护,于是往下看……

T2,是一道计算几何?!给你 \(n\) 个平面上大小不同的圆,每次选择一个半径最大(若半径相同则标号最小)的圆,删掉它以及和它有交集的所有圆。求最终每个圆是由于谁删掉的。

暴力?暴力?有时间再骗分!下一题。

T3,给出一个简单无向图,求选出三元组 \((s, c, t)(s \ne c, s \ne t, c \ne t)\) 的方案数,须满足存在至少一条从 \(s\) 出发,在 \(t\) 结束,且经过 \(c\) 的简单路径,答案取模。

这什么东西?感觉跟双连通分量很有关系?好像缩点之后 dp 一下?细节好多啊 QwQ,不过有好多部分分!

于是先回去重新看一眼 T1,打算完善一下刚才“随便一个数据结构维护”的那个细节在脑中完善一下,发现懵逼了……

直接线段树?可能要对于每个种类都维护一棵啊,查询也需要在每棵上都查一下,复杂度爆炸!

怎么办呢?是不是可以二分?!二分一个距离,然后这个位置往左往右扩这么多距离所形成的区间必须包含所有的种类,好像主席树可以维护?等等主席树的话,需要以位置为版本号,值域上维护的是上一个超市的位置啊;这样不好维护修改啊(场后想了一下感觉似乎可以用树状数组套主席树实现,但是感觉无敌难写,当然这个二分是非常有价值的)……

陷入沉思……最重要的是要抓出所有种类的超市之和不超过 \(n\) 这个限制!除了超市不超过 \(n\) 个,还有什么不超过 \(n\) 个呢?诶,每种超市的相邻位置之间夹的区间也是 \(O(n)\) 个的,并且一个二分区间不合法(就是没有包含所有种类)一定会出现某个种类的区间包含了它这样的情况,那么我们只需要判断这些区间中是否有完全包含它的区间即可!至此转化成了一个二维数点的问题,其实只需要询问一个矩形区域内是否有点即可,所以对于每个区间左端点 \(l\) 上开一个堆维护最大的 \(r\) 即可。这样好像恰好是两个 \(\log n\) 的,\(5\texttt{s}\) 的实现肯定没问题!

开写!过了一些时间(我也不记得多长了,代码不是很复杂),写完了,小小地调了调过了样例,交一发,WA \(0\)……

什么情况?写个暴力!交一发,\(5\) 分……那就和暴力对对拍吧……

拍出了几个错,大概是在用 multiset 时出的技术问题,调完了交一发……T 了!\(47\) 分……(我忘了具体分值了,大概就是这个左右)

于是开始打 fread 读入优化、输出优化、*************(此处和谐若干卡常过程)

最后还是没卡过,只有 \(57\) 分,有两个 subtask 没过。(本地也 T 了,大概是 \(6.7\texttt{s}\) 左右)

我发现没过的有一个是 \(\forall i \in [1, n], a_i = 1\) 的子任务,这个东西可以倒过来变成只有加入操作,省掉一半的常数;我复制了一下代码改了改,交了上去(利用了它可以自动拼部分分的功能),变成 \(80\) 分了。

我不甘心这道复杂度能 A 的题因为常数问题过不去,于是就对着代码干瞪,显然我的代码在插入、删除操作时,对线段树里面套的堆的操作占去了大部分时间,于是我就主要瞪这里……

然后我就发现我 SB 了,这个东西在线段树的叶子节点上套堆就行了,我在每个节点上都套了个堆……改了一下,修改复杂度降为一个 \(\log n\)(但是询问复杂度还是两个 \(\log n\)),成功通(卡)过了本题。

一看表发现 \(3\) 个小时过去了……凉啊……

T2 迅速打了一个 \(7\) 分暴力,跑去搞 T3……

T3 我上来就写 tarjan 缩点,目标直接设定成 AC……我想一点部分分都不拿如果最后没写出来太亏了,而且树的部分分可以帮忙检查我想法的正确性(树的子任务的程序是标解程序的一小部分),所以我先做了一下那个子任务,拿到 \(23\) 分,本来还想写环的,但是考虑到有多个连通分量,我决定把时间留给正解……(这里决策太失误了 QAQ)

在最后的时刻我的“正解”过掉了样例,交了一发,肯定等不出结果了。就这样比赛结束了,以凉凉(带着一点小期待)收场。(当然最终这个期待被证实是完全多余的)

晚上照旧颓……

5 月 13 日

回了趟家,下午回去听课,讲的自动机……

【这好像是唯一一次在八十中吃晚饭?】

晚上颁奖典礼之前玩了一下琴,感觉这个琴有一点跑调,手感也很奇怪【其实就是给自己弹不好找借口】看到另外一位大佬弹神曲 orz

我们学校的舞蹈队来表演辣 ~(≧▽≦)/~,赞!实在是太棒了!表演了两场舞蹈,最后一场舞蹈撒花瓣撒的满台都是……最后她们自觉清理掉了。

颁奖仪式显得分外冗长,蒟蒻我在台下祈祷着不要在铜牌、银牌名单里看到自己的名字……CTSC 成绩差的有点远(最后拿了一个 Ag),APIO 勉强卡线 Au……


这次 APIO 在最后一题上出现了决策的失误,我太贪了,想在最后 \(40\) 分钟打出正解,但显然不可能。我当时应该清楚认识到自己不擅长这种问题并且看出部分分非常好拿并且分数很多,而且最后这点时间肯定反馈不了信息,无法验证正确性,所以就应该好好写部分分,况且它自动将每个子任务分数取 \(\max\),我没能好好利用这一点真是可惜了。如果我最后一题求稳拿部分分的话就不会这么苟且地拿到 Au 了……



在写这个总结时我还发现另外一个问题,我有两次在考场上对一道题的第一反应出来的做法是错误的,后面回过头来看时才发现,然后重新思考……

这可能是一个隐患问题,我可能会低估这题的难度而导致策略安排上的巨大偏差。

解决办法就是:

  • 考试开始后先看完三道题,这样可以对整体难度有一个把握,即使对某题的难度判断失误,在发现后仍可以灵活调整。
  • 第一次想错难以避免,由此可见 “Think twice, code once” 的重要性,在没有正确性和时间复杂度的完全把握时绝不敲代码(当然乱搞除外)。