线段树四倍
马拉车开两倍!(需要插入通配符)
有时候随手写个暴力很快,不用对拍,就在原代码里写,然后把输出比较,这样有时会让效率提高很多
O 如果你企图用这种方法:printf("%d.%d",ans/100,ans%100)来以小数形式输出百分数,那就要自闭啦
问:102/100=? 102%100=? 102.0/100=?
O 张帆(主席)犯过的DP错误:dp[0][0][0]=0,其他都是-inf
第一维表示直到第i个物品,dp[i][j][k]从dp[i-1][j-1][k-1]和dp[i-1][j-1][k-3]转移
那么这样就会导致从第2个物品开始,(0,0)的状态不为0,相当于强制后面的物品上前面的车,不能从头选
应该给所有物品的(0,0)都初始化为0
为什么背包没有这个问题呢?
因为背包所有物品都dp在一个维度上呀,dp的时候一定要注意了
O 网格图的点数要特别注意
你以为是n个点?其实是n*m个点哒
这个在开数组,判断爆int等步骤都容易出错
O 一个dfs时复杂度分析的错误
我枚举n^2条边,对于每条边都花O(n)检查是不是树边,如果这条边是树边(n-1条),那么就枚举选或不选并搜下一层
这样其实并不是2^n*n的复杂度,因为n^2的枚举和2^n的枚举是相互交织的,n^2并不能被2^n覆盖掉,总复杂度差不多还是2^n*n^3量级
所以还是别偷懒用O(n)检查,先用并查集预处理出树边再搜吧。。
O 当通过返回oo来控制二分中贪心的无解的时候
注意是否会爆int(很可能会的,所以还是慎用oo啊,用了尽量开longlong吧)
O 当你在递归或dfs中使用队列或栈的时候一定要小心了!
大多数时候所有的递归层数共用一个队列,如果不退栈将导致可怕的后果
事实上,即使保证每个点至多只入队一次,如果多层递归同时用一个栈的话,还是必须记录当前层的栈顶位置
所以还是尽量避免多层共用吧,先预处理好,再一次性做完队列该做的事
O 用阶乘预处理法求组合数时一定注意,注意检查阶乘预处理的范围
尤其是方格里求组合数,阶乘的范围是[0,n+m-2]而不是[0,n],也不是[1,n],注意求0
如果只预处理了0到n交上去必WA,肯定又要怀疑结论错了,损失惨重,切记啊!
这个易错点再次说明手测最大数据的必要性
O id函数初始化和统计答案的时一定注意!
统计的不是1到n,而是0到id(n,m)(或者别的范围)
id函数易错点,只要出现id函数必须列入常规项检查
O 多维id函数解压易错点:如果id=x*m*4+y*4+z,那么y=id/4%m而不是id%m/4,注意顺序
O 使用id函数压缩状态的时候一定注意最小的id是不是0,以及会不会造成影响!!!
例如last[t]!=0这个判断,就可能在id为0的状态前停下,而不是一条链的开始停下
再比如初始化的时候,容易写成从1到idmax初始化,把0漏掉导致错误
O 一个剪枝中的贪心错误
左边有n个点有一个权值a[i],如果这个点总共被选d次,那么它对答案的贡献就是a[i]^d
右边有n个点,每个点必须选择一个左边的和这个点连边的点
思考:启发式函数中,右边的某个点对答案的启发式函数h是否能设置为与它连边的所有点中a最小的那个?
不是!
当a=1时,如果某个点第二次被选,它对答案的贡献是0而不是至少是1
O 如果数据不是特别大,不妨先写一个简单的启发式函数,TLE了再尝试优化,不要一上来就写很复杂的启发式函数,导致出错就得不偿失了
O 读入字符串时字符串的数组一定不要开成刚好的大小!!!
因为scanf读入后会添一个 ,如果数组大小刚好就越界了。。。
所以还是不要省什么内存了,每个数组都尽量有点冗余,免得又有什么奇奇怪怪的错误
O 判断所有的点能否到达T一定不能偷懒原图bfs或dfs!
必须建反向图
O 倍增求lca的注意事项:
注意如果要同时维护区间和,区间最大值的时候(边权),最后x和y往lca合并的时候,由于二者是从同深度共同向上,因此两人的(边的)值都要考虑到
if(x==y) return mx;
else return max(mx,max(mst[y][0],mst[x][0]));
O 计算几何检查点:跟eps比的东西有没有abs
没加abs就傻b了哈哈
O 不管是手写堆还是用STL,比较优先级的时候切忌进行dis[x]>dis[y](dis是全局数组)这种比较
因为dis会变,堆里用来比较的dis不是入堆时的值,修改dis会导致堆结构混乱
O 大坑!python读入字符串的时候会去掉 但是不会去掉 ,所以python尽量避免全句匹配!
一般是windows在记事本里手打数据造成的
O 幂取模的时候注意指数要对(mod-1)取模
检查的时候注意有些计算函数可能放在指数上面,函数里的模数也要是mod-1
O 一种错误的DP写法:
O dfs回溯的时候注意检查完全,不要光盯着循环里看,函数开头dfn类似的可能也要回溯
O 给你一个区间的左端点和长度,范围1e9,那么坐标的范围是2e9而不是1e9,因为1e9+1e9=2e9
O 要求你统计字符串中出现的字符中出现的次数并升序输出,注意没出现的字符可是不输出的哦。。。
O 10点40的时候时针不在10上!涉及到钟表的几何问题可能掉坑
O 如果把2位小数转整数,(long long)(b*100)不可取,b=0.57时得到0.56,应该+eps
O double的有效位数大概到16为,一个1e15的整数乘一个两位小数,再转成longlong就可能丢精度了,应该给小数乘100再除回去
O double强转int的时候注意可能要加括号,例如(int)a*b,如果a是整数b是浮点数,而想让a*b变成浮点数就傻了,应该(int)(a*b)
O 如果要输出整数部分,注意算清数据范围,有时候不能用(int)a而是(long long)a
O 两个值为1e10的long long相乘结果大于0
O 用multiset的时候,注意erase是删除所有相等元素,并返回删除元素的个数
O 注意别把2e5的数组开成1e5
O 鸡兔同笼问题中,有a个头,b只脚,判断数据是否可能的条件不是2a<=b<=4b,而是b%2==0 && 2a<=b<=4b!
O 强连通分量缩点+拓扑排序千万不能偷懒不缩点!!
不缩点而用标号代替的后果不仅是WA(拓扑DP的最优值有滞后性),还会RE(不缩点是假dag,还是有环的)
O 用余弦定理时注意判断是否构成三角型,3中情况都必须判断到,很容易漏
O 直角坐标转极坐标的时候注意α不是arccos(Δx/l),arccos的范围是[0,pi],还需要判定Δy
O 长度为0的序列错位排序方案数是1不是0
O 如果对dp的f数组做前缀和,注意f的初始状态如果不为0,那么前缀和中,对应一层的初值都不为0
O 有些dp使用滚动数组可以直接赋值,无需清空数组,但是注意有一些赋值不到的地方(比如f[i][0])可能需要清空
O 出现灵异错误时可以注意一下局部变量是不是没初值,尽管这个错误在初学者里很常见,但熟练者一旦出现实际更为棘手
O 线段树区间赋值注意delta的空值是否能为0,因为区间赋值很多时候都存在把区间赋值为0的情况,这时delta空值不能是0
O 检查数组大小时要注意某些值的范围可能变化,例如缩点+背包,那么包的容量可能就会增大
O SPFA(包括费用流)队列长度应该比点数多,因为可能重复进队
O 用字符数组的时候不要把下标为0的当做长度,char可以装数字但是只能装很小的数
O 浮点数比较相等的时候,注意是abs(a-b)<eps,而不是a-b<eps
O 有时候sort会巨慢,如果次数比较多就很难受
这时如果结构体排序,可以在比较函数前加'&',即参数取地址,防止每次函数调用都把结构体复制一遍,可以跑得飞快
当然也可以手写堆排序,难度不大
O 浮点数二分不能这么写:
应该算出循环次数后直接for,否则在32位机上会因为精度问题死循环
O 如果main函数里ans没有初值,而ans相关的语句只有ans=min(ans,...)和cout,编译器是不会报错的(可能是把min那句当成赋值了)
这个时候会一定概率输出正确答案,当ans初值随到比答案大的时候就正确,否则WA 233
O
O 用printf四舍五入时需要+eps,防止丢精度
O 字词删除的权值线段树不能这么写(功能是找给定范围内的权值最大值)
if(z<=md) return qry(x<<1,l,md,z); else return max(qry(x<<1,l,md,z),qry(x<<1|1,md+1,r,z));
会T飞,要这么写:
if(z<=md) return qry(x<<1,l,md,z); else if(z<=r) return max(qry(x<<1,l,md,z),qry(x<<1|1,md+1,r,z)); else if(v[x<<1|1]) return qry(x<<1|1,md+1,r,z); else return qry(x<<1,l,md,z);