1005考试总结
1005比赛总结
时间线 Time Line
08:00 开始考试
08:00 开 $A$
09:45 结束 $A$,开 $B$
10:10 结束 $B$,开 $C$
11:00 开 $\text{Excel}$ ,跑 $C$ 大样例
11:45 结束 $C$,开 $D$
12:00 结束考试
结果 Result
$A;;40,pts.$ (低于预期)
$B;;80,pts.$ (高于预期)
$C;;35,pts.$ (低于预期)
$D;;0;,pts.$
(不好评价)$Total;;155,pts.$
从排名来看高于预期,从绝对得分来看符合预期。
总结 Summary
首先,这次比赛最大的一个问题是时间的安排,$A$ 与 $C$ 题均耗费了一个小时以上的时间,导致 $B$ 与 $C$ 题只有很少的时间写。戏剧性的是,$B$ 只耗费了 $25\text{min}$ 却是本场比赛中拿分最高的题。
其次则是思路上的问题,$A$ 题在赛时有正解的想法,但是因为没有仔细下去或是不敢往下想而放弃(那时已经 9:10 了,因此不敢拿剩下的时间去赌这道题)。$C$ 题也是如此,在提交代码后大约 $30\text{s}$ 就找的了赛时没找到的 BUG。
最后就是码力上的问题,其实也是因为思路被禁锢了,$C$ 题明明有一种写起来+调起来都更舒服的方式,可惜没想到,导致耗费了大量时间在调试上。
这告诉我什么?
及时止损,切换思路
提高码力,估准难度
仔细思考,加强深度
合理化时间分配
关于知识点的联系
暴力!暴力!暴力!!!不会也得打暴力!
第一阶段总结
第一阶段主要是关于动态规划的序列问题的,可以分为两种:
最长公共子序列(LCS)
最长上升子序列(LIS)
首先,LIS可以用来求LCS,其时间复杂度为 $O(n\log n)$ 。
最长公共子序列又有几个经典问题:
求长度(模板)
求方案数:动态规划+转移计数
求方案:动态规划+转移倒推
求字典序最小方案:动态规划+统计字母出现位置
给定两个字符串求最短包含串的方案(数):动态规划+双指针
而最长上升子序列的问题就多了去了,以下只列一些:
求长度(模板)
求字典序最小/大方案(动态规划+贪心递推)
求方案数(动态规划+计数+ $O(n\log n)$ 树状数组或二分优化)
求本质不同的方案数(同上,加个去重)
求LCS(用一个序列“离散化”另一个序列)
判断一个数是否出现在LIS上(动态规划$O(n\log n)$+统计位置:一定在序列上的数位置不变,不一定则位置可能变化)
构造指定长度的LISDL序列(不好说)
一阶段的问题主要都体现在1005的比赛中了,比赛中的问题就是要解决的问题。
关于最长上升子序列的 $O(n\log n)$ 写法:
1. 二分
空间复杂度 $O(n)$ 即数组长度空间。
这种方法本身不能求出具体方案,可以求出最长上升子序列的长度。
其原理简单来说就是对于每次新加一个元素,看它是否能接着当前这个序列下去,如果不能,则找到最小的一个大于(等于)它的元素并替换。
代码实现如下:
1 | memset(g, 0x3f, sizeof g); |
(f
数组的定义和朴素转移一样,$f_i$ 记录以 $a_i$ 结尾的最长上升子序列)
2. 树状数组
注意:本方法空间复杂度为 $O(k)$ ($k$ 是 $a_i$ 的取值范围)
所谓优化,要么在算法上优化,码量小,但难想;如果在数据结构上优化,码量大,但是基本不动脑子。
具体而言,我们做出如下分析:
优化什么?第二维
j
的转移。怎么优化?树状数组,对值域开数组,每次转移拿当前的 $a_i$ 的值查询并更新树状数组。
如何证明正确性?感性理解,分析朴素转移中有哪些限制:①. $j<i$;②. $a_j<a_i$。①我们在循环更新的过程中从未往数组中加入 $i\leq j$ 的元素,自然也不会从后面的状态转移过来;②因为我们是对值域开数组,因此在当前 $a_i$ 前面的一定是那些 $a_j<a_i$ 的状态。
至此,所有问题均被解决,剩下的只是代码实现了(这里不贴代码了,待会连着统计方案数的题一起贴)。
注意树状数组只是优化哪些数能被转移以及加快转移过程,不是把 f
数组开到树状数组上!
有了这些法宝,接下来就看例题啦!
经典例题
例一
题目:给定字符串 $a$ 和 $b$ ,求最短的字符串 $c$ ,使得 $a$ 与 $b$ 均为 $c$ 的子序列。输出所有满足条件的 $c$ 中字典序最小的。