P2441M 见过的 tricks
有时候见过的 trick 还是想不起来,感觉还是有必要做这个啊。
数据结构
- 时间相关的操作,可以:
- 区间问题有时可以仅利用线段树结构维护信息。例题:P11536。
- 历史版本相关操作,可以考虑离线建出版本树。例题:CF2026F。
- 头尾插入删除,可以通过维护对顶栈变成头尾插入撤销,一边栈空时从另一边栈取一半过来重构,均摊线性。这也是 STL deque 的实现。例题:CF2026F。
- 在线段树的节点上维护
multiset/priority_queue以支持区间插入删除。例题:P12019。 - 可以用分块降低空间复杂度。例题:HDU7171,P9260。
- 前后缀最值可以考虑使用单侧递归线段树维护,在节点上维护右儿子状态。例题:P4198。
- 线段树分治可以通过离线把删除转化为撤销。例题:CF576E,P3733,CF678F,LOJ121。
DP
- 转移时填表和刷表都要想,两者并不本质相同,有时只有其中一种适用。例题:ARC207C,CF2038D。
- 处理一个序列的所有排列一类的问题,可以:
- 计数类问题性质比较复杂时,先考虑判定。例题:P10375,P9753,AGC022E。
- 可行性 DP 可以考虑换维变成最优化 DP。例题:P12546,CF1144G,P4728,CF1647F。
- 一些限制相关的问题,考虑按限制从严格到宽松处理,可以更具体地表现为:按值域的某种顺序填数、倒序 DP 等。例题:ARC162E。
- 使用容斥放宽限制便于 DP。例题:P6846(DAG 容斥),P11714,P3349,P14303。
- DP 状态有用值比较少时,可以考虑线段树合并做整体 DP。例题:P6773,P5298。
- 末尾状态可以启发 DP 状态的设计。例题:P10041。
- 树形 DP 状态与根链相关时可以考虑重链剖分。例题:P5391,HDU6566。
- 看起来很难优化的 DP 可以考虑 CDQ 分治。例题:QOJ7899。
- 贡献提前/延后计算,在当前 DP 状态下无法良好维护的东西延后到后面的状态中计算。例题:P2365,P14364,CF1608F。
- 可描述为线性变换的 DP,如果需要跑多次,其中转移过程完全相同,只有初值的差别,则可以考虑转置原理,将 DP 倒过来做。例题:UOJ823、CF1810G。
数学
- Raney 引理可以用于求解一类前缀和非负的计数问题。例题:P6672,P12969。
- 形如 \(\prod(v_1+v_2+\cdots)\) 的式子可以直接考虑用乘法分配律展开。例题:P10045,CF1842G。
- 使用辗转相除法求 \(n\) 个数的 \(\gcd\) 复杂度是 \(\mathcal{O}(n+\log{V})\) 的(势能分析)。例题:P11694。
- 组合意义天地灭。
- 无向图 \(G\) 中,所有 \(1\) 到 \(n\) 的路径构成的异或线性空间存在大小为 \(m-n+1\) 的线性基:考察 \(G\) 的一棵 DFS 生成树 \(T\),每条非树边对应的环都在线性基中。例题:P4151。
- 推论:无向图 \(G\) 中 \(1\) 到 \(n\) 的简单路径最多只有 \(2^{m-n+1}\) 条。例题:ABC419G。
- 倍数限制可以取 \(\log\) 转化成差值限制。例题:P4926。
- 加减法可以拆位,考虑是否进位,变成 \(\bmod{2^k}\) 意义下的偏序关系。例题:P13997。
- \(\min/\max(x,y)=\dfrac{x+y\pm|x-y|}{2}\)。例题:P12391,P10197。
- 对于含 \(n\) 个数的可重集 \(S\),考虑其线性基 \(B\),则 \(S\) 的所有子集异或和有 \(2^{|B|}\) 种本质不同的数,每个数出现 \(2^{n-|B|}\) 次。例题:P4869。
- \(\mu^2(n)=\sum_{d^2\mid n}\mu(d)\)。例题:SP4168,P4318。
- 期望相关的 DP 式子会转移回自己时,可以考虑解方程。例题:P3412。
- 卷积形式的 DP,可以考虑以较低复杂度算出若干点值,再插值回去。例题:CF1874E。
- 组合数行前缀和相关考虑用 \(\dbinom{n}{m}=\dbinom{n-1}{m-1}+\dbinom{n-1}{m}\) 拆成除了最后一项都出现了 \(2\) 次的形式。例题:P13688,ABC235G。
- \(|x|+|y|\) 可以拆成 \(\max\limits_{p\in\{-1,1\},q\in\{-1,1\}}\{px+qy\}\)。例题:CF1859E。
位运算
- \(\operatorname{and},\operatorname{or},\gcd\) 一类的操作会使得值域减半,从而使得有效值只有 \(\mathcal{O}(\log{V})\) 个。例题:ARC207C,CF2038D。
- \(\operatorname{and},\operatorname{or}\) 相关可以从 \(\operatorname{popcount}\) 入手考虑。例题:P10743。
- 从 \(a\) 中取出两个数 \(a_i,a_j(i\neq j)\) 使得 \(a_i\operatorname{and}a_j\) 最大,只需要保留 \(a\) 的前 \(\lfloor\log V\rfloor+1\) 大来计算答案,可以归纳证明。例题:B3930,P2326。
- \(\operatorname{bit}_k(a+b)=\operatorname{bit}_k(a)\oplus\operatorname{bit}_k(b)\oplus [(a\bmod 2^k)+(b\bmod 2^k)\geq 2^k]\)。例题:P13997,CF1188D。
树上问题
- \(k\) 级祖先、\(u\) 在 \(v\) 方向上的儿子等一类祖先链相关问题,可以离线下来后维护 DFS 栈 \(\mathcal{O}(1)\) 求解。例题:P12933,P11976。
- \(dep\) 相关贡献可以放到根链上考虑实际意义。例题:P4211,P5305,P9808。
- 区间 LCA 等于区间内所有相邻两点的 LCA 构成的点集的 LCA。例题:P11364。
- 点集 LCA 等于 DFS 序 \(\min,\max\) 的 LCA。例题:P11976。
- 形如给一条祖先链上未赋值的点赋值的操作可以使用树上并查集均摊维护。例题:P11976。
- 考虑树上的两条链,对两条链的端点两两求出 \(4\) 对 LCA,那么以最深的那两个点为端点的链就是两条链的路径交。例题:HDU6110。
- 树上三点两两间的路径必然交于一点。例题:P10105。
图论
- 图论问题经常考虑 DFS 生成树转化成树上问题。例题:P11976,CF1361E。
- Bellman-Ford/Dijkstra 求最短路可以推广成图上 DP 的形式,同样要满足松弛的贪心性质。两者的区别在于 Dijkstra-style 的 DP 通常满足某种单调性。例题:P13534,AGC072E,CF827F。
- 偏序关系考虑图论建模。例题:ARC165D。
- 形如权值差不超过 \(1\) 的限制考虑图论建模后变成欧拉回路/路径相关。例题:P9731,CF1610F,P7816。
- Hall 定理存在多种推广:
- 平面图满足欧拉定理,即 \(|V|-|E|+|F|=C\)。例题:P3776。
- 拓扑排序时,当前出队的点和队列中剩余的点不可达。例题:CF1062F。
- 最小化路径上最大边权的问题考虑建出最小生成树求解。例题:P1967,P2245,P13548。
- 二分图边染色可以 \(\mathcal{O}(nm)\) 地把二分图划分成多个完美匹配。例题:P10062。
- 竞赛图 SCC 个数可以刻画为,将点集划分为两个可空点集 \(A,B\),使得 \(A,B\) 间所有边都是 \(A\) 连向 \(B\) 的方案数减 \(1\)。例题:ARC163D。
- 考虑一张连通图上的最小生成树,对于任意一种合法的加树边方案,加入所有边权 \(<x\) 的树边后图的连通性都是一样的。例题:CF891C。
序列相关
-
可以考虑使用 \(0/1\) 序列刻画判定条件。例题:ARC176D,NowCoder 115997C,P10093。
-
考虑对序列 \(a\) 进行冒泡排序,设经过 \(d\) 轮冒泡后得到的序列为 \(a'\),则 \(a'[1,x]\) 中的元素就是 \(a[1,\min(x+d,n)]\) 中的元素从小到大排序后的前 \(x\) 小。例题:P12865。
-
可以这样刻画一轮冒泡排序:对于每个前缀最大值,把它平移到下一个前缀最大值之前;对应地,每个非前缀最大值会恰好向前移动一个单位。例题:P12865,ARC187C,P4372。
-
括号序列问题可以考虑求匹配时的栈结构。例题:CF1340F。
-
任何一个长度为 \(2n\) 的合法括号串 \(s\),都可以用如下方式构造出来:
- 初始时令 \(s_1\leftarrow\texttt{(}\)。对于 \(2\leq i\leq 2n\),令 \(s_i\leftarrow\texttt{)}\)。
- 枚举 \(1\leq i<n\):
- 将 \(2i,2i+1\) 加入集合 \(A\) 中。
- 若从 \(A\) 中取出一个元素 \(x\),令 \(s_x\leftarrow\texttt{(}\)。
本质上是反悔贪心状物。例题:ABC407E。
-
极小 \(\operatorname{mex}\) 区间只有 \(\mathcal{O}(n)\) 个。例题:P9970,P13693。
-
序列本质不同 \(cnt\) 个数是 \(\mathcal{O}(\sqrt{n})\) 级别的。例题:P13688,P5072。
字符串
- 平方串(也就是形如 \(XX\) 的串)相关问题,考虑枚举 \(|X|=len\),在字符串中每隔 \(len\) 个位置放一个断点,这样每个长度为 \(2len\) 的平方串都会经过恰好 \(2\) 个断点,把问题转化为相邻段的 LCP 相关。例题:P1117,CF319D。
- 字符串子串比较可以用 Hash 二分求出 LCP,在 LCP 后一位比较,从而做到 \(\mathcal{O}(\log{n})\) 比较,常数较小。
- 一个字符串的所有排名在 \([L,R]\) 中的后缀的本质不同前缀个数为 \(\sum\limits_{i=L}^r(n-sa_i+1)-\sum\limits_{i=L+1}^Rht_i\)。例题:P4143,P3181,P4248。
计算几何
- 一次函数 \(\min/\max\) 考虑维护凸壳。例题:P12569。
- 使用射线法判定一个点是否在多边形内。注意处理射线穿过顶点的情况,可以多射几条,也可以精细实现,让每个点恰属于一条边。
- Quick Hull 求凸包:确定凸包边界点后分治,用左右点的连线切凸包求出切点作为递归中点。其实和 WQS 二分没什么区别。例题:P5540。
- 平面最近点对存在期望线性做法:维护前缀答案 \(d\),将平面以 \(d\) 为边长网格化,对每个网格枚举相邻的 \(3\times 3\) 的网格更新答案,若答案被更新则重构。例题:P9062。

浙公网安备 33010602011771号