CSP-S 2021 爪巴记
Day -1
和 sxy 在家里打原神,打了一上午。。。。
下午疯狂默写各种数据结构、数学板子。
Day 1
上午坐车去了日照,没啥好说的,下午考试。
提前进了考场试机,发现万恶的 CCF 用 c++14 评测,但是本地的编辑器只能开到 c++11 ,太草了。
花了半个小时打了快读快写、对拍程序,默写了一些数据结构。
14:30
拿到题面,遵循 “Think twice,code once.” 的原则,我前一个小时是基本不会写代码的。
14:45
翻开 A 题题面,分配廊桥的决策显然具有单调性,离散化+二分切了
15:00
扔了看 B 题,鬼畜字符串计数。我个人最不擅长的就是计数、数学、字符串,这题戳到了我的两个痛点,稍稍感到不妙,但是我很快平复了心情。
似乎可以枚举每一个 '?' 字符是 '(',')','*' 中的哪一种,这样可以写一个 (O(3^n)) 的爆搜出来,得 15 pts。
15:15
转去看 C ,给了个特殊性质但是考场上没看出来怎么用,非常恼火。
暴力挺好打的,(O(2^{2n})) 枚举答案序列然后 (O(n)) check 就好了,这样得 28 pts。
15:35
D 题看起来挺草,不像是我能做的题,仔细读了读之后选择放弃了。
15:40
回去写代码,发现 A 的思路有大问题。
首先这个答案由两部分组成,一部分是国内的贡献,另一部分是国外的贡献。
设分配 (x) 个廊桥,国内的贡献为函数 (f(x)),国外的贡献为函数 (g(x)) 。
如果我们给国内分配 (x) 个廊桥,那么答案就是 (p(x)=f(x)+g(n-x)) 。
这里显然 (f(x)) 单调递增,(g(n-x)) 单调递减,那么根据高中数学的知识,(p(x)) 不一定具有单调性。
那么二分的做法就假了,猜测正解可能是枚举 (O(n)) 然后 (O(log n)) check 。
16:05
先去写了 C 的暴力,20 分钟过了小样例,感觉没什么问题。
回去分析 A 的性质。
16:35
罚坐了半个小时,摸不着头脑,感觉很危,决定先打一个 40 pts 的暴力,把低保拿了。
17:05
暴力写完了,并且 3 个样例全都过掉了,应该没什么问题。
看了看 B ,感觉 check 非常难写,剩下的时间不一定能写出来,转去给 C 加点剪枝。
17:35
剪枝写好了,大样例跑了 40s ,但是过掉了。
看 C 的特殊性质分,想了 20 分钟没想出来。
18:05
突然,发现 A 实际上可以乱搞一波。
我们实际上要求的是函数 (p(x)) 的最大值,它可能是一个多峰函数,因而二分、三分都没法做。
但是如果某个值 (x) 使得 (p(x)) 很大,那么最优的 (p(x)) 很可能就在这个 (x) 附近出现。
考虑对答案区间 (n) 分块,把每个块的端点带入函数 (p(x)) 跑一遍,得到一个最大的端点值。
在这个端点的相邻两个块内枚举 (x) 的值,带入求解 (p(x)) ,取最大值。
重复选取 3 个不同的块长,3 次所得答案取优输出。
假设块长为 (T) ,那么总复杂度是 (O(Tn)) 的,常数略大,不过正确性似乎还不错。
18:20
光速写完分块,把 3 个样例都过了,稍微放心了一点。
剩下的 10 分钟罚坐,并拷问自己为什么这么菜。
18:30
退场
出了考场
发现同机房的人好多切 A 的,搞得我心态比较爆炸。
在车上,我跟 sxy 讲了我的分块乱搞做法,他直呼卧槽,并且奶我是分块大师。。。
然后我们一起给这个算法想了一个名字——“答案分块”。
Update:10.28
这个分块的做法在各大 oj 的民间数据测的结果在 70-85 分左右,难道我靠这个乱搞的分块翻盘了吗?
总之,我被吊打了。