【视频讲解】:考试易错点讲解_哔哩哔哩_bilibili
如何避免 TLE 超时问题
前言:在语法结构上,99.9% 的超时都是由于循环引起的
超时的可能原因:
如何解决:
由数据范围反推算法复杂度以及考察的算法
说明:
0. 有的时候, 数据范围给我们的提示可能比原题还要多。
1. 一般情况下,C++代码中的操作次数控制在 10^7107 为最佳。
2. 不同代码的常数差别很大,所以 1s 和 2s 的区别不大,都可以认为上限是 10^8108。
下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:
数据范围 | 时间复杂度 | 考察的算法 |
---|---|---|
n \leq 30n≤30 | 指数级别 | dfs+剪枝,状态压缩dp |
n\leq10^2n≤102 | O(n^3)O(n3) | floyd,dp |
n\leq10^3n≤103 | O(n^2),O(n^2\log n)O(n2),O(n2logn) | dp,二分,朴素版Dijkstra,朴素版Prim,Bellman-Ford |
n\leq10^4n≤104 | O(n*\sqrt{n})O(n∗n) | 块状链表,分块,莫队 |
n\leq10^5n≤105 | O(n\log n)O(nlogn) | 各种sort,线段树,树状数组,set/map,heap,拓扑排序,dijkstra+heap,prim+heap,spfa,求凸包,求半平面交,二分 |
n\leq10^6n≤106 | O(n)O(n),常数较小的 O(n\log n)O(nlogn)算法 | hash,双指针扫描,并查集,kmp,AC自动机,常数较小的 O(n\log n)O(nlogn)算法:sort,树状数组,ST表,heap,dijkstra,spfa |
n\leq10^7n≤107 | O(n)O(n) | 双指针扫描,kmp,AC自动机,线性筛素数 |
n\leq10^9n≤109 | O(\sqrt{n})O(n) | 判断质数 |
n\leq10^{18}n≤1018 | O(\log n)O(logn) | 最大公约数,快速幂 |
n\leq10^{1000}n≤101000 | O((\log n)^2)O((logn)2) | 高精度加减乘除 |
n\leq10^{100000}n≤10100000 | O((\log n \times \log\log n))O((logn×loglogn)) | 高精度加减,FFT/NTT |
-
常犯的错误
- 注意 数据范围 !!!定义单个变量能用long long 就不要用int,能定义为double就不要用float。
- maxn、minn(最大值、最小值)或者cnt(计数器)忘记 赋初始值 。
- 忘记 取消freopen的注释 ,或忘记删除用来检查代码的语句,比如添加了多余的打印操作。
- 文件名或者freopen里面的名称抄错。
- 没理解题目的意思,就开始做题。要 结合样例去理解题目 。
- 注意题目数据范围很大的时候, 考虑优化 。
- 数组 开太大。比如:int arr[10000][10000],则arr的空间大小约为400M,远超 题目的空间限制 。关于数组开多大可以。
- 边界条件考虑不充分。
- 变量命名 与c++自带的名称冲突(因此,慎用万能头文件)。如:int time; int max; int min; 等等。
- sort里面的 cmp函数 ,从小到大和从大到小没搞清楚。
- 写了 初始化函数 ,没有 调用 。
- 使用 函数 时, 参数 传错。
- 用了一个新的知识点,但自己不太清楚,就用了。要注意,写的代码最好是你完全能明白的。
- if里面的判断条件 没想清楚,还继续往下写。
- 循环里面条件写反,比如: for(int i = n; i > 0; i++)
- 双重循环里面 j 和 i 写反,或者两个 循环变量 都写成i。
- 字符串string中,遍历string的操作最好用for(int i = 0; i < s.size(); i++),不要用小于等于i <= s.size() - 1
- 虽然数据范围不大,但是输入数据量比较大,比如需要输入/输出 100 万个数字。这时,cin/cout 语句的执行时间就需要考虑进去了
- 循环层数太多或循环范围太大
- 选择的算法不是最优的算法
- 读入优化:使用 scanf 和 printf 替换 cin 和 cout,用 '\n' 替换 endl (原因这里不做展开讨论)
- 循环优化:循环层数优化(比如 P1096:百钱百鸡问题 就可以从三重循环优化为两重循环)、循环范围优化(比如判断素数使用 <=sqrt(n) 替换 <= n)
- 选择正确的算法:质量越高的题目,越会在数据范围上下足出题者的心思,好的题目的数据范围是有 层次感 的。如果出题者想考察某个算法,那么在数据上,他会让用 暴力枚举 方法的同学只得 60分,使用 另外一种方法 能得 80分,只有使用 最优算法 的同学才能得 100 分。关于这一点, 也请同学们在读完题目之后,多思考一下,本题有没有其他更快的算法。
- 卡常,一般小学组的题目不会考察卡常,请读者按需要选读。关于卡常的几个注意点: 4.1. 运算符速度比较:+、- 快于 * 、/ 快于 a[] 4.2. 能用递推,就不用递归 4.3. 尽量减少函数调用