[总结] 比赛相关
策略*
- 看题:
- 注意时间、空间限制;
- 适当猜测正解的知识点、算法、trick、复杂度 (可以适当枚举);
- 观察题目的突破口:
- 注意记录灵感 (比如和 xxx 题目好像啊,是不是可以从 xxx 条件入手,xxx 条件是不是无意义条件……),以免无法回溯;
- 注意从多个方面思考问题,时间轴上扫描线/序列轴上扫描线,考虑每个元素对答案的贡献/考虑每个位置对答案的贡献。
- 在入手思路不唯一的时候,不要轻易断定谁是正解,因为解法的可拓展性是无法一眼估计的。
- 阅读数据范围 (尤其是数据范围比较复杂的题目,同时注意数据范围可能出现在任何位置,比如输入格式),初步估计暴力分,哪怕是最低档,也看看是否容易实现;同时也可以通过数据范围猜算法。
- 可以手玩样例确保读题正确。
- 做题:
-
首先对于看题时得到的灵感进行一定的深入思考;
-
如果猜了结论,使用反例证伪,而不是觉得不行 (感性证明,理性证伪);
-
测试极限数据 (如果会出现考试中不愿意写 m.cpp 和 p.cpp,可以看题前写);
-
-ftrapv
,-fsanitize
和size./a
这样的命令,不要等到最后检查的时候再用,以免来不及修改。 -
不要过分依赖命令查错 (以下是必须自己注意的问题):
-
long long 赋值给 int 发生的整形溢出。
-
同一个数组中的越界等 (指超过一维的数组)。
-
vector 等动态开的空间。
-
-
- 实现:
- 看起来没区别的处理方法,也尽量日常写的频率较高的。
- 对于无解等特殊情况,不要想当然认为程序能够正确处理,最好试一试。
- 最后的检查 (离考试结束还有 30min 的时候就要开始):
- 阅读程序,确保实现的逻辑和自己想的一样。
- 检查是否 return 0 了,时空复杂度。
- 测试所有的样例 (哪怕是看起来很水的样例);
- 检查文件名是否正确,目录是否正确。
心态
- 大胆猜测,小心求证。
- 不安心的话,先写会的分。
- 重要的是拿分的难度,不是客观难度。
- 对于似曾相识的题目,注意这两点:
- 各种限制变强还是变弱;
- 数据范围变大还是变小;
错误
低级错误
- 数组开小:\(N\) 的大小错误,没有 \(+5\),用到 \(5\) 刚好开成 \([5]\),FFT 数组要有结果那么长。
- 初始化不完全。
- 没有算空间。
- 写错模数。
- 乘法不取模。
- 打错字母。
- 函数没有返回值。
- 不测试极限数据。
中级错误
- 前导零判错。
- 时间复杂度算错。
- INF 大小不对。
- 需要的时候没有稳定排序。
- 没有处理斜率为 \(\inf\) 的情况。
- 取模优化没有 \(-\bmod\)。
- 给
long long
排序的时候cmp
传的int
,这种将long long
给int
赋值的行为,命令行是检查不出溢出的。 - 对 STL 中的模板 pop 一个空的队列,或 delete 一个不存在的元素。
高级错误
- 没有考虑没有边的单点这种特殊情况。
- 没有考虑添加空点,空字符对答案的影响。
- 存在多种拓展方式的 bfs 是否不同拓展会相互干扰。
- 可以多项式快速幂 \(\log\) 的东西乘了 \(n\) 次。
- 维护点值可以 \(O(V)\) 合并的东西因为维护系数结果 \(O(V\log V)\) 合并。
- 对于分块,当前块修改时,有值是从前面的块传过来,没有考虑前面块的标记的影响。
技巧
拆,都可以拆*
- \(dis(i,j)=dep_i+dep_j-2\cdot dep_{lca(i,j)}\)
- \(\varphi(i\cdot j)=\varphi(i)\cdot\varphi(j)\dfrac{\gcd(i,j)}{\varphi(\gcd(i,j))}\)
- \(\text{整个排列的逆序对数} = \sum_{i=1}^n\sum_{j=i+1}^n [a_i,a_j\text{构成逆序对}]=\sum_{i=1}^n a_i \text{之前} > a_i \text{的数的个数}\)
卷,都可以卷*
- \(id=\varphi\ast1\)
- \(\varepsilon=\mu\ast1\)
- \(\varphi=id\ast\mu\)
容斥,都可以容斥
- \(\sum_{i=1}^n\sum_{j=1}^n[lca(i,j)=x]=siz_x\cdot (siz_x-1)-\sum_{y\in son_x}siz_y\cdot (siz_y-1)\)
卡,都可以卡
- 区间查询的线段树:可以选择时间换空间,对于小于一定长度的区间,选择暴力获得原本维护的结果。
优化,都可以优化
- 状态转化成判定类,bitset 优化转移。