写代码的一些小技巧&错题本(持续更新)
对double类型数组初始化:
无穷大0x42;无穷小0xc2。
模板类的read函数:
防止读longlong类型的数字时爆int
template<class Type>
inline Type read(void){
Type x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
读int类时int a=read<int>();
,读longlong类时LL a=read<LL>();
。贼好用。
线段树防写炸
在pushdown的时候,把更新子节点的值写进一个函数,在Update的时候也能用,防止手抽写炸。
inline void Add(int o,int v){
add[o]+=v;
sum[o]+=len[o]*v;
minv[o]+=v;
maxv[o]+=v;
return;
}
inline void pushdown(int o){
if(!add[o])return;
Add(lson,add[o]);
Add(rson,add[o]);
add[o]=0;
}
inline void Update(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){Add(o,v);return;}
//Do something
}
滚动数组
可以开两个数组f和g,f表示当前i阶段的DP数组,g表示i-1阶段的DP数组。
for(register int i=1;i<=n;++i,swap(f,g))//转移
{
//do something
}
树上求链交
求链(a,b)与(c,d)的交。
设c1=lca(a,b),c2=lca(c,d)c1=lca(a,b),c2=lca(c,d),且排序后dep[c1]≤dep[c2]dep[c1]≤dep[c2]。
设d1=lca(a,c),d2=lca(a,d),d3=lca(b,c),d4=lca(b,d)d1=lca(a,c),d2=lca(a,d),d3=lca(b,c),d4=lca(b,d),且排序后dep[d1]≤dep[d2]≤dep[d3]≤dep[d4]dep[d1]≤dep[d2]≤dep[d3]≤dep[d4].
两条链有交当且仅当dep[c1]≤dep[d1]dep[c1]≤dep[d1] 且dep[c2]≤dep[d3]dep[c2]≤dep[d3],此时d3d3与d4d4是两条链的交。
Splay函数
注意在Splay函数的最后写一行update(x)
,否则有可能会有未知错误。
inline void splay(int x, int goal) {
for (int f; (f = fa[x]) != goal; rotate(x))
if (fa[f] != goal) rotate(get(x) == get(f) ? f : x);
if (!goal) root = x;
update(x);
}
multiset的erase函数
multiset是可重集,但是erase函数却有一个小坑。就是如果erase函数传参是传的是“数值valval”,它就会将集合中所有valval全部删除。
但是如果传一个迭代器,它就只会删除一个元素。
注意题目中的限制
有一道题是这样规定的:0≤k<n0≤k<n,如果这样规定,那么kk就不能等于nn。一定要注意这样的小细节。
用单调队列实现决策单调性优化DP
注意在判断 ii 是否是最优决策的时候用的是小于等于还是小于。
如果用的是小于,注意特判 ii 不是任何点的最优决策的情况。
int pos = -1;
while (hh <= tt && f[i] + w(i + 1, q[tt].l) < f[q[tt].p] + w(q[tt].p + 1, q[tt].l)) {
pos = q[tt].l;
-- tt;
}
if (hh <= tt) {
if (f[q[tt].p] + w(q[tt].p + 1, q[tt].r) > f[i] + w(i + 1, q[tt].r)) {
int l = q[tt].l, r = q[tt].r;
while (l < r) {
int mid = (l + r) >> 1;
if (f[i] + w(i + 1, mid) < f[q[tt].p] + w(q[tt].p + 1, mid)) r = mid;
else l = mid + 1;
}
pos = l;
q[tt].r = pos - 1;
}
}
if (pos != -1)
q[++ tt] = Node(i, pos, n);
KMP算法
KMP算法在算法开始之前需要保证nxt数组是空的。所以如果多次用到nxt数组,注意清空。
读入 n or m?
在读入的时候一定要看清是读入 nn 还是读入 mm,特别是当样例中的 nn 和 mm 相同的时候。
注意空间复杂度
有时候在做题的时候,可能会着重考虑时间复杂度,而忽略的空间复杂度,导致最终写出来的程序由于空间过大而得到很低的分数。
做题前要看空间限制,如果是 256MB 及以下就要小心了!
乘法要注意 long long
int 类型的乘法一定要注意是否强制类型转换成 long long 类型。
O(1) 时间内实现 long long 乘法取模
LL mult(LL a, LL b) {
return (a * b - (LL)((long double)a / P * b) * P + P) % P;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现