曾经掉过的坑
前言:一篇非常好的博客,考试前一定要看:https://www.luogu.com/article/gbpkw48t
STL汇总极力推荐 \(xjy\) 大佬的博客》》》点我!
坑
-
十年\(OI\)一场空,不开\(long long\)见祖宗。(要用脑子判断开不开)
-
多测不清空,亲人两行泪。
-
看清变量名,不要重复定义,更不要看错打错,不要定义太多\(a,b,c,d,e\)这样的变量名。
-
复制粘贴时一定要仔细检查,不要漏改、眼花。
-
循环变量时看好\(i,j\),逆序循环时一定是\(--\)。
-
全局定义后的变量不要在局部再次定义。
-
continue是到循环为止都不再执行,不要因为if else忘记。
-
定义数组时一定要注意是否爆int, 不要定义像 \(dp[30][500005]\) 这样的数组,还有,不要盲目复制粘贴代码。
-
memset
慎用,初始化最好for循环。 -
像 \(dp[i][j]=min(dp[i][j],dp[i+1][j]+(a[i]==k))\) 这种语句 \((a[i]==k)\) 不能拿出来另外判断!
-
链式前向星要开2倍。
-
强制在线一般都有
if(l>r) swap(l, r);
这样的语句。 -
取模最好每乘一下都取模。(尤其是 \(+=\))
-
暴搜一定要算好最大值,避免求 \(\max\) 时出锅。还有边界条件。
-
考试时不要用
endl
!!!不想换printf
就用#define endl "\n"
-
莫队无输出多半是板写错了,务必仔细检查。
-
线段树修改查询操作判断r<=mid和l>mid后面传的参数一定是lid/rid, l, r!!!
-
排序后才能去重!!!排序后才能去重!!!排序后才能去重!!!
-
struct 如果不封装就不能在数组上用
memset
! -
并查集 fa[x]==x?x:fa[x]=find(fa[x]); 警钟撅烂
-
求最值只要>=1e9必赋值1e18。
-
可撤销并查集不能路径压缩。
-
标记反向边edgenum要从1开始。
-
关键字坑惨了。
数论
-
如果无输出,很可能是N的值太大了。
-
如果输出为0,很可能没有使用init()。
-
如果模数很小,要考虑lucas定理。
-
当没有模数的时候,直接用组合的公式即可(\(f[n]/f[m]\%p/f[n-m]\%p\))。
-
如果不明情况TLE或RE,可以考虑换写法。
-
init 函数最好最大循环到 n。
位运算及图的子集相关
-
for(int T=S;T;T=(T-1)&S)
可以不重不漏枚举 S 二进制下的所有子集。 -
s>>(i-1)&1
可以判断 s 的第 i 位是不是1。 -
s|(1<<(i-1)
可以将 s 的第 i 位变为1。 -
s^t
能求出 t 在 s 里的补集。 -
一个图的子集数量等于 \(2^{边数}\) 。
-
如何求一个点集的连通子图 S 个数?(设 \(f[S]\) 表示 S 的连通子图个数, \(g[S]\) 表示 S 的子图个数)
钦定一个点 \(u∈S\) ,把不连通子图分成两部分:包含 \(u\) 的连通块,不包含 \(u\) 的其他部分。
根据容斥原理:\(f[S]=g[S]-\sum_{u∈T⫋S} f[T]*g[以 S 为全集求T的补集]\)
一些总结:
-
求方案数时,首先考虑\(dp\),然后考虑组合数学,可以用逆向思维去想。不会就用暴搜。
-
如果树状数组无输出,多半是遇到0。
-
TLE时,可以考虑将一些数组预处理出来,一些递归函数不要重复调用(例如循环里求同一个数的逆元、线段树函数调用)。如果只超时几毫秒,可以考虑快读优化。或者endl换\n。
-
dp题里最关键的部分(影响答案的,也就是决策点),往往就是dp数组需要维护的东西。
-
一定要审清题,考试时一定不要放弃思考。
-
如果拿到题没有思路,可以手模一下样例,或者从部分分写起,试试找规律、猜结论。
-
RE
有可能是循环越界了。 -
调试代码时可以分段调!!!这样子效率能提高很多!!
-
如果
TLE
实在调不出来,可以将一段整体的代码写成函数调用。(比较玄学) -
RE
(段错误)有可能是函数返回值错误。 -
有时倒序处理问题比正序更简单。
-
bool 数组比普通数组要快。