满脸心酸泪的改错本

本人(蒟蒻)几经 风(WA) 风(dao) 雨(zi) 雨(bi),列出如下巨坑:

    1.循环顺序出错(区间DP)。

    2.数组定义小了,题目(迷宫,线段树,链接字符串,数组两边循环,主席树)给的n,m并不是实际真正储存的大小。计算的时候一定小心,并且做完要检查。

    3.设边界的时候一定要注意,画个草图出个简单数据模拟一下,少一多一都是无尽的懊悔。

    4.<还是<=,整除还是小数,诸多判断的细节问题,一定要把题目抠透,每个条件都罗列出来,保证不重不漏。

    5.freopen.

    6.long long是个巨坑啊,有时候数据特猥琐,表面上看起来不会炸int,但是中间的运算过程也可能要炸,一定要注意。输入输出的时候windows系统是"%I64d",(大写的i)但评测环境Linux系统是"%lld",(小写的l),一般如果要交上去测用"%lld",不要弄错了(cf是用的%I64d)。有的题更坑,涉及到10的几次方的,数据抵着longlong的上界,最后乘个10就炸longlong了,要用unsigned long long。

    7.多次的修改操作不要在一堆优化之后忘了修改。。。

    8.多组数据清零。。。

    9.mod如果中途有负数(比如说容斥),最后的ans一定要(ans+mod)%mod  !!!   还有有的mod是1234567891之类两个int加起来都会炸掉,attention!!! 还有注意不要把INF累加,取min!

    10.全局变量在递归里面当成局部变量用会 十 (WA) 分 (dao) 快 (zi) 乐 (bi)。。。(dfs,带权并查集)

    11.判断二进制数x的第y位是否为一, 用x>>y&1,而不要用x&1<<y,因为后者的结果可能是2的几次幂,在if判断==1的时候很容易错

    12.struct node{ node(int a,int b):a(a),b(b){} } 里面的node(int a,int b)最好不写成node(int a=0,int b=0),那样内存会大十倍。。

    13.dfs如果递归层数不多并且代码短也推荐加inline...

    14.当你发现自己的代码几乎和别人一模一样然而自己就是WA或者RE,或者把别人代码粘过来就能过自己就是过不了,多半是数组越界改到了下一个数组的0位置什么的。。数组越界往往会有自闭也调不出来的奇怪错误(而且往往是些出负数的错误)。。

    15.那种需要unsigned int的恶心数据范围用1<<31的时候注意,这样是错误的,需要1u<<31或者1ll<<31,而且1u<<32是0(2019省选D1T1因此爆零。。)

    add:建Trie树的空间,如果有k条边,就有k+1个点,空间要开maxn*(k+1)(<2^k就是k条边)

    16.当你把一个数组排序后需要用到原数组下标的信息时,注意把数组按照编号排回来再用(或者另外开一个数组存下原来的信息)

    17.dfs用vis数组判环或者费用流的时候,注意最后的vis=0是否被执行了,不能中途return。基环树判环的时候如果是无向图二次访问要比较深度,如果是有向图要判断是否在栈中。

    18.求逆元的时候用x^(mod-2)次方一定要注意mod是不是素数。。(有的题是输入mod,习惯性求逆元就打成mod-2次方。然后自闭,应该是φ(mod)-1次方)

    19.two pointer以及类似双指针移动时的修改操作要注意是否正确,多数时候操作是可逆的,移动右端点的修改要在移动左端点时撤销

    20.写线段树的时候一定不要忘了pushdown和pushup(特别是没写函数的时候注意维护)

    21.树上求直径的时候注意边权,不要把dis顺手就写成dep。。

    22.把id[i]=i数组按照A数组的权值排序后用的时候记得是id[i]而不是直接代i。。。

    23.基环树之类有特殊处理的图要注意图是否连通,特殊点集可能有多个

    24.对于NOIP级别的字符串恶心模拟题,最好使用getchar(),特殊字符和空格换行之类注意测试,文件末尾可能没有换行注意判断EOF。

    25.背包的时候一定注意作减法不要数组越界!!!

    26.当题目既有取最值又有取模操作的时候,注意最值应该用原来的值来取,而不能用模后的值!!!

    27.写KD树的时候一定要检查估价函数,注意longlong,还有nth_element的时候不要忘了加上cmp!(没写cmp不会编译错误这就很难受啊,而且小数据还试不出来。。。)

    28.斜率优化的时候毒瘤出题人如果把范围开到了1e16以上,比较斜率以及输出的时候就得用long double了,另外,斜率优化的时候注意除了按x排序,x相等时还必须要按y排序才能保证弹栈正确!(如果是x有序而y无序可以用 P-S[tp] 与 S[tp]-S[tp-1]比较斜率(用叉积的话就只能加特判了)。

    29.O(nlogn)~O(1)求LCA的时候注意ST表的大小是2*n!倍增的时候也注意循环边界是2*n!

    30.写点分治的时候注意点分树上的父亲不要存成树上的父亲了!点分树上的儿子是需要返回的!

    31.写双哈希的时候如果两个都用ULL注意取模的那一个中间过程不能为负(ULL没有负数)!

    32.计算几何涉及到点积叉积什么的不要随便取fabs,可能正负会决定方向的!

    33.写2^log(数值)的方法时候注意数组大小不是开n而是开2^log(数值)!!特别是把原数组当成记录个数数组的时候!

    34.cdq分治的时候注意第一维相同的时候要按第二维排序!

    35.把id[i]按照另一个数组的权值排序的时候一定不要忘了写sort(id+1,id+1+n,cmp); cmp!!!!!

    36.当数据结构(线段树/LCT)中有维护“子树中最左/最右的关键点”的信息并且有区间翻转标记的时候,要么把信息改为存子树中是否存在关键点,然后在询问时二分;要么就最左和最右要同时存,翻转的时候交换信息,不能只翻转标记而不翻转左右信息!!

    37.合并两块信息的时候(vector.resize,闵可夫斯基),特别是那种初值为两边第一项的,注意判断是否有某一块为空!

    38.数学题推式子,涉及到组合数等,注意求和的范围是可能根据组合数 n>=m 缩小的,从而简化组合数的运算。

    39.考试写拼盘暴力的时候一定要注意某个版块执行之后要return 0 / exit(0),不要再进到其它情况去,尤其是调试修改完后很容易忽视这一点,注意检查!!


一些小小的总结:

    1.关心数据范围,很多时候范围会给你正解的类型,让你找到正确的方向,而且空间时间也得注意

    2.让自己保持轻松的心情做题,不急不慢。

    3.拿到题,思考它的类型,该不该用学过的算法,或者是数学方法,亦或是枚举,正解往往并不超出自己所学,只是自己没有真正的学透罢了,掌握思路与方法是AC的关键,至于实现代码的能力,就要靠刷题来堆砌了。

    4.0不能作除数,运算除法的时候一定要保证分母变量不为0,想方法规避这个问题,有时候这问题很致命,可以用来判断问题是否有解。

    5.尽量让你的程序通俗易懂,一些细节思考清楚,需不需要特殊处理,有时候程序的算法实际上可以避免一些看起来很特殊的数据,让每个if都有价值,如果你的程序需要特殊处理的太多,那么一定不是好的程序,一定要理清程序到每个阶段应该干什么事,到哪里要处理,怎样处理最简单,最正确,思考完备再动手。

    6.高精度运算在位数较多时容易超时,可以考虑压位处理(详情请见高精度开平方  

    7.想骗分就要做得绝一点,尽量优化,有些很显然的优化会起到很明显的效果,特别是排排序什么的。算法的精髓就在于按一定的顺序解决问题。

    8.bitset加上中途退出甚至可能过掉1000的n^4...信仰很重要。

    9.实在想不出来就重建思维模型,换个方向,或者换个解法。

    10.不等式问题可以转化为最值问题,譬如任意x>1可以翻译为x的最小值>1,存在x>1可以翻译为x的最大值>1。这个小trick比较常用,也很巧妙。

    11.DP时如果遇到状态有后效性,可以尝试将其写入状态,或枚举某些量,或按照某种顺序逐层转移。

    12.做数论题的时候如果有gcd(a,b)=1的条件,意味着a在模b意义下有逆元,可能大幅简化做法。

    13.做交互题的时候如果经过一番理论分析询问次数足够实际运行却多了很多,怎么调参都没变化,很可能是某个地方写错了,或者有显然的优化没有加(特别是别人写法差不多却很轻松就过去了的情况)。


考试时应当注意的事项:

    1.重中之重:数组越界,取模(注意不要写成x+=(...)%mod),long long(1ll不要在括号很多的时候乘错了位置),边界,文件名,空间大小。

    2.构造小数据测试,注意各种特殊情况,严谨推导。

    3.生成最大规模的数据,测试是否超时,RE等。

    4.暴力对拍。对拍过了一定要注意自己的理解是否与题意有偏差,某些变量的范围是否是自己理解的那样(要是暴力和正解同时出锅就真的难受了。。)

    5.考试结束前10分钟一定要检查是否输出了调试信息,文件名和文件位置是否正确。

    6.C++11也出了挺久了,见机行事吧,有时候确实很方便。

(持续连载中......)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值