注意:本文转载自这个大佬
不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分! 不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分! 不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分! 不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分! 不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!不要挂分!
写在前面
下面的内容中每一个挂分小技巧:
第一行是指出了错误,第二行及以后说出了正确做法(可能没有),
如有不是的会特别指出,请注意。
常见的挂分小技巧
-
在结构体里开数组开的太大。
这种情况下即使没爆空间也会出现许多奇怪的错误。 -
数组的下标减出负数导致 RE。
请一定注意这个地方,一定要加一个判断,数组下标一般不能是负数!(除非你用map) -
使用了结构体,导致内存不连续访问被卡常。
-
数组嵌套过多被卡常。
-
输出 ull 但不知道 printf 对应的占位符,宁肯瞎猜也不用 cout。
这种情况请使用 cout。 -
比较两堆数的乘积大小直接乘了起来导致爆掉
应取 log 函数进行比较。(清北国庆刷题营Day3T1、洛谷P4370组合数问题) -
设置最大值时比给出数据的最大值还要小。
-
设置最大值时注意数据范围。
-
复制粘贴代码后没有修改充分导致出现错误。
这种错误的解决方法就是:认识检查或者直接重写而不是复制粘贴。 -
做完题之后不检查。
我就是生动的例子,只过样例不可靠,样例一般都是精心设计好的,一定要自己多造几组数据。
检查很有用,但是也不保证检查一定会查出错,不保证不会改错。 -
在使用 sqrt()
函数 或 pow() 函数 时没有进行类型转换。
注意 sqrt() 函数的返回值 和 pow()函数的返回值为浮点数。 -
滚动数组忘记清空。
滚动数组不清空,爆零两行泪。在 DP中经常会用到滚动数组来降低空间复杂度,为了避免意外的错误发生,请记得清空已经用过的滚动数组。 -
全局变量和快读的局部变量相同都会读入一些奇奇怪怪的东西。
这个我好想没遇见过……不过学弟都说了就放上来吧。
printf 里面 %llu 写成 %ull。
读入字符用 scanf。
用 scanf 中的 %c 来读多个用空格隔开的字符时,它会去读空格。这个时候我们可以这么写:
char s;
//在 %c 前加一个空格
scanf(" %c", &s);
-
随时计算 for 循环的上界。
for循环的上界不要随时计算, 复杂度可能爆炸, 类似于 i<=sqrt(q),i<=strlen(s)。 -
位运算不注意优先级导致运算出错。
位运算的运算优先级很低,所以在不了解优先级的前提下,建议位运算加括号。 -
(特别指出,此处为正确做法)注意实数二分的精度问题, 实数输出的精度问题。
-
(特别指出,此处为正确做法)在struct 中, 写重载运算符时注意格式。
-
(特别指出,此处为正确做法)在操作时注意数组边界, 包括枚举时超出定义大小, 和枚举的部分应不应该有初值。
取模中的挂分小技巧
-
模数取错。
-
不随时取模。
注意取模,看好两个数相乘的结果是否会爆出你所定义的类型。
当然也不是取模越多越好,因为取模本身比较慢,所以应该在合适的地方取模。 -
(特别指出,此处为正确做法)在取模时注意负数的取模。
本质为手误的挂分小技巧
- in 和 out 文件写错,正确写法(根据题目而定):
freopen("a.in", "r", stdin);
freopen("a.out" ,"w", stdout);
-
莫名其妙在代码里多加了几个符号。
-
奇奇怪怪的手误,比如:变量写错,i 和 j 写反,f[y][i] 写成 f[y][y],s=read(),t=read() 写成 s=read(),s=read()。
规范写法, 能写 k>0 就不写 k, 循环变量要多变,不要只写 ijk, 冗余信息可以减少出错。
本质为脑抽的挂分小技巧
-
不写读入。
-
数组开小。
-
快读把字符写成整形。
-
自作聪明,不看题目要求。
-
认真读题啊,先把题目多读几遍圈画出重要信息再做
-
更小的数组,更多的挂分。
-
该开 long long的题没开 long long。
-
多测不清空,爆零两行泪。
多组数据记得清空,注意清空要完全。 -
炸空间,或者空间开小,有的题空间开小不一定会 RE,还有可能会 WA。
-
不好好看看数据范围。
数据范围十分重要!直接决定了你的分数! -
$2^{31}$比$0x3f3f3f3f$大!
-
在有返回值的函数中不加 return。
-
不给局部变量赋初值。
-
自以为开了 longlong 但在一处微小的地方没开 longlong。
认真检查,杜绝发生。 -
写有 else 的 if 语句时忘记写 else。
图论中的挂分小技巧
普通
-
带权边建成无权边。
-
双向边建成两条一样的单向边。
不要求快,要求准,用好自己的手和眼。
倍增求LCA
-
倍增lca 把根节点的深度设成 0
-
不是很常见,这样无法和跳到 NULL 区分。
最短路
-
单向边建成双向边
-
单向边,单向边!
-
有向图建成无向图
-
有向图,有向图!
建树
- 读入一棵树的时候读入了 n条边。
一棵树是一张有 n 个点 n−1条边的连通图。
矩阵中的挂分小技巧
- 矩阵不写初始化。
矩阵记得初始化,我的写法如下:
struct matrix {
int a[A][A];
matrix() { memset(a, 0, sizeof(a)); }
void init() { for (int i = 1; i <= n; i++) a[i][i] = 1; }
};
- 将矩阵交换后相乘。
矩阵乘法不满足交换律,请不要这样使用
数据结构中的挂分小技巧
不知道放到哪儿
- 一系列需要动态开点的数据结构(主席树,SAM)没有继承之前状态的信息。
单调栈
- 初始化单调栈,set中没有加入极值。
主席树
-
吝啬空间,空间开小。
一定不能吝啬空间,开 30倍左右? -
在主席树中,if (k <= tmp) query(t[x].l, t[y].l, t[lca].l, t[fa_lca].l, l, mid, k); 中的 k<=tmp 写成 k>=tmp。
在 build函数中,忘记加 now,答案没错,但是程序运行十分缓慢。
void build(int &now, int l, int r) {
t[now = ++tcnt].sum = 0;
//debug:t[now = ++tcnt].sum = 0写成t[++tcnt].sum = 0;
//忘记加now导致程序运行速度十分缓慢
if (l == r) return;
int mid = (l + r) >> 1;
build(t[now].l, l, mid), build(t[now].r, mid + 1, r);
}
线段树
-
query,update函数中的 l,r 写成 l,mid 和 mid+1,r
如果是用结构体记录了每个区间的左右端点,那么函数中的 l,r指的是要查询或要修改的区间,这个区间的端点应该是不变的。 -
吝啬空间,空间开小
至少开 4倍空间,最好不止 4 倍,特别是当 n 达到 5e5级别时,要千万注意。 -
权值线段树维护的值域 出现了负数,没有添加偏移量。
LCT
- LCT旋转时最后更新祖父信息。
虽然 splay 可以这么写,但 LCT中由于之前的操作改变了结构,写法不当会导致祖父的信息出错。
STL中的挂分小技巧
- (特别指出,此处为正确做法)类似 堆 和 vector 的 STL 在使用的时候, 要注意是否为空
DP中的挂分小技巧
状压DP中的挂分小技巧
- 状压DP的时候写错运算符 (fl & l) → (fl && l)
背包DP
- 背包转移时枚举顺序出错。
字符串中的挂分小技巧
(和字符串有那么一丢丢关系的的就都放这了。)
普通
- 没有注意 char类型的上限是 127,写了 ‘z’+6 导致爆掉。
trie
- 用 trie处理二进制问题时,存储从高位到低位存 和 查询却按照低位到高位查。
数学中的挂分小技巧
- 质因数分解漏掉 <x−−√的至多一个质因子。
应用到C++特性的挂分小技巧
-
声明数组时赋初值。
-
注意C++的特性:若在声明数组时为其赋初值,则会将整个数组遍历一边来赋值。 即使这样写: a[1e7] = {1} , 它仍然会遍历数组,并将 1~1e7-1 赋为0。 造成时间爆炸式浪费,以致编译超时,还会造成MLE。
很淦的挂分小技巧
-
考 NOIP的时候踢电源线。
这个小技巧实在是太狠毒了,不仅会让你挂分,还会让别人挂分,真是干得漂亮太恶毒了。 -
考试闹情绪。
-
删库。
-
在freopen 前边写读入。
-
激情码码码正确率高达 100% 然而忘了 prework(预处理)。
-
在主函数里调用 return main();。
高精度中的挂分小技巧
- 写高精高精数组开得太大
写高精的时候,封装经常会用到memset,高精数组开太大会导致memset时长加n倍,一定要估计好题目最大数的位数然后决定这个数组的大小
可能会导致挂分的小技巧
- 使用 cmath 中自带的 max、min 函数可能会比自定义函数慢
LCT中当父亲是连通块的根的时候pushup祖先会不太对
(但是谁LCT还多pushup几次的,嫌常数不够大么)