OI trick 总结
\({\color{green} 1.整除分块}\)
\(i \bmod j = i-j \times \lfloor \frac{i}{j} \rfloor\)
例题:ABC452E
\({\color{green} 2.恰好变至多}\)
若要求恰好为 \(k\) 的个数,则转化为 \(\le k\) 的减去 \(\le k-1\) 的。
例题:ABC452F
\({\color{blue} 3.Lantern 技巧}\)
若要求覆盖所有点,则可以设 \(dp\) 状态为前 \(i\) 个点能覆盖的前缀。
例题:
\({\color{cyan} 4.异或最小值}\)
对任意 \(a < b <c\),有 \(a \oplus c > min(a \oplus b,b \oplus c)\)
例题:p10200 花神诞日
\({\color{cyan} 5.加入两段}\)
若有两个组别,把序列 \(a\) 按顺序加入两个组中的一个,则一定有一个组结尾是 \(a_i\),只需记录两个组中的另一个的结尾。
例题:
\({\color{purple} 6.最值分治}\)
若答案于一个区间的最值有关,考虑用单调栈求出每个位置 \(i\) 作为最值的区间 \([l_i+1,r_i-1]\)。
然后对每个位置的区间枚举子区间,枚举较短的一边,另一边用数据结构维护。
例题:
\({\color{cyan} 7.神秘树}\)
若 \(2y > x\),则 \(x \bmod y + y \bmod z \ge x \bmod z\)
例题:
\({\color{purple} 8.SCC 个数}\)
翻转有向图若干条边的朝向。
条件1:第 \(i\) 条边被操作后,\(u_i\) 仍然可达 \(v_i\)。
条件2:\(v_i\) 原图中就可达 \(u_i\)。
当且仅当两个条件只有一个满足时,SCC个数发生变化。
例题:
\({\color{purple} 9.直方图转笛卡尔树}\)
见到直方图,考虑把每一行最低的一列作为当前笛卡尔树节点编号,递归到下一层建出整棵树。
每个节点可能要存高度,宽度。
例题:
\({\color{cyan} 10.车占棋盘}\)
一个 \(n \times m\) 的矩形,选 \(k\) 个位置放棋子,要求一行,一列都只能放一个。
方案数为\(\binom{n}{k} \times \binom{m}{k} \times k!\),其中 \(k!\) 是把行和列对应起来的方案数。
例题:
\({\color{green} 11.Dilworth定理}\)
一个偏序集的最小链覆盖等于其最长反链的大小。
例题:
\({\color{blue} 12.dfn序DP}\)
一个树结构如果儿子对父亲节点的选择有依赖可以转为 dfn 序。
例题:
\({\color{blue} 13.枚举非法}\)
如果一个题目条件约束下,不合法的只会有一个元素,比如某某不能使用超过 \(\lfloor \frac{n}{2} \rfloor\),则枚举这个不合法元素,让总方案减去所有不合法方案。
例题:
\({\color{green} 14.记录差值}\)
如果只关心两个数的大小关系,就可以不去记录他们分别是多少,而记录他们的差值,可以让 DP 减少一维。
\({\color{purple} 15.连续段DP}\)
组合对象为一个序列的排列,从数值小到大放入某个位置进行生成,会形成若干连续段,只关心有多少个连续段以及他们的端点,而不关心其内部结构。
例题:
\({\color{cyan} 16.拆位}\)
位运算每一位间相互独立,可以对一位单独考虑。
计数时可以考虑每一位的方案数再求乘积。
例题:
\({\color{blue} 17.赋权哈希}\)
当一个弱化的条件无法正确判断时,用随机赋权哈希来加强正确性。
例题:
\({\color{purple} 18.弹飞绵羊}\)
若经过一个位置会造成一种影响,则把位置分块,预处理经过每一块的影响,支持动态重构块。
例题:
\({\color{green} 19.邻接矩阵乘法}\)
对有向图的邻接矩阵 \(A\) 做矩乘,则 \(A_{i,j}\) 为从 \(i\) 出发走 \(k\) 步到 \(j\) 的方案数。
建立一个源点0,令 \(A_{j,0}=1\),\(A_{0,0}=1\),则 \(A^{k+1}_{i,0}\) 为从 \(i\) 到 \(j\) 步数小于等于 \(k\) 的方案数。
\({\color{blue} 20.区间lca深度}\)
\([l,r]\) 的 lca 深度为 \(\min_{i=l}^{r}{dep_{lca(i,i+1)}}\)
例题:
\({\color{cyan} 21.二分图}\)
二分图没有奇环。
最大匹配。
最小点覆盖=最大匹配。
最大独立集=\(n\) - 最大匹配。
最小路径点覆盖=\(n\) - 拆点二分图最大匹配。
\({\color{purple} 22.动态树直径}\)
树的直径=\(\max_{1\le u,v \le n}{dep_u+dep_v-2 \times dep_{lca(u,v)}}\)
用欧拉序表示树,\(le_u\) 表示 \(u\) 第一次再序中出现,\(re_u\) 表示最后一次出现,\([le_u,re_u]\) 即为 \(u\) 的子树。
\(dep_{lca(u,v)}\) 是 \([\min(le_u,le_v),\max(re_u,re_v)]\) 中深度的最小值。
用线段树维护 \(mx,mi,lmx,rmx,tag,ans\)。
可以做到动态维护树的直径。
例题:
\({\color{blue} 23.天天爱打卡}\)
当 \(n\) 很大,但是决策点数量远小于 \(n\) 时,只对所有决策点进行离散化。
例题:
\({\color{green} 24.奇怪转换}\)
\(k^2 = 2 \times \binom{k}{2}+k\)
\({\color{blue} 25.种树}\)
一棵树有 \(n\) 个需要激活的点,每个点激活后会以不同的速度增长,求出每个点在当前限制下最晚的激活时间 \(t_i\),按 \(t\) 升序排序,若当前未被标记则把根到 该节点都标记,只要中途没有点超出时限则合法。
例题:
\({\color{gray} 26.正难则反}\)
反向思考/时间倒流。
例题:
\({\color{purple} 27.划艇技巧}\)
暴力DP设 \(dp_{i,j}\) 为第 \(i\) 个对象其取值为 \(j\),\(j\) 处在一个区间内,但 \(j \le 10^9\),考虑把区间两端离散化为左闭右开,设状态为 \(dp_{i,j}\) 表示第 \(i\) 个对象的取值落在第 \(j\) 段内。然后对每一段进行考虑。
例题:
\({\color{blue} 28.选出严格递增序列}\)
从区间 \([0,L]\) 中选出长为 \(m\) 的非零数严格递增序列,方案数为 \(\binom{L+m}{m}\)。
例题:
\({\color{purple} 29.旋转坐标系}\)
当操作是沿45度斜着移动,考虑将坐标系旋转45度,即点 \((x,y)\) 变为了 \((x-y,x+y)\)。这样一次操作就只有一维会改变。
例题:
\({\color{cyan} 30.展开余数}\)
对于 \(\lceil \frac{a_i-a_j}{d} \rceil\) 想要分离 \(i\) 和 \(j\),可以把 \(a_i\) 和 \(a_j\) 表示为 \(q \times d+r\) 的形式,则原式等于 \(q_i-q_j+[ri \ge r_j]\)。
例题:
\({\color{purple} 31.最值限制}\)
限制 \([l,r]\) 间的最大值为 \(x\),可以转化为全部小于等于 \(x\),和至少一个等于 \(x\)。区间至少有一个 \(x\) 的方案数为 \(x^{len}-(x-1)^{len}\)。
例题:
\({\color{purple} 32.点段离散化}\)
将离散化后的端点间的一段视作一个点,将端点的下标乘以二,中间就会空出奇数下标作为段的下标。
例题:
\({\color{cyan} 33.攻略技巧}\)
要求一棵树选出 \(k\) 条叶子到根的路径,使得这些路径的点的并集点权和最大。考虑带权长链剖分,取权值和最大的前 \(k\) 条长链即可,因为父链一定大于子链,且长链一定连接叶子节点,所以可以成立。
例题:
\({\color{green} 34.倍增跳转}\)
大步跳转:单次模拟步数太多。
确定性转移:从状态A出发,下一个状态B是唯一确定的。
单向性:坐标或时间是单调递增的,不会回头。
结合性:跳 \(2^k\) 步可以由两个 \(2^{k-1}\) 步合并而来。
例题:
\({\color{cyan} 35.树上流平衡}\)
叶子节点只能依靠父节点来改变度数,可以递归向上,依次处理。
例题:
\({\color{cyan} 36.逆序对反推}\)
已知一个排列每个位置的前缀逆序对数和,可以推出唯一的排列满足要求,从后往前扫,二分当前位置填哪个数能满足他要创造的逆序对数。
例题:
\({\color{blue} 37.区间状态DP}\)
不知道怎么说。
例题:
\({\color{cyan} 38.反悔贪心}\)
用堆维护反悔操作的增量。
例题:
\({\color{purple} 39.冒泡排序刻画}\)
一轮冒泡排序为枚举 \(i\) 从 \(1\) 到 \(n-1\),若 \(a_i > a_{i+1}\) 则交换。若经过 \(c\) 轮冒泡排序后,某个数最多往前平移的位置数就是 \(c\),所以 \([1,x]\) 的结果为 \([1,x+c]\) 中前 \(x\) 小的数。
求 \(c\) 轮后 \([l,r]\) 的和就是原数组中 \([1,r+c]\) 前 \(r\) 小的和减去 \([1,l-1+c]\) 中前 \(l-1\) 小的和,用主席树维护。
主席树求前 \(k\) 小的数的和要求维护出现次数和其值的和,注意当递归到 \(l=r\) 时不是返回值的总和而是此时的 \(k \times x\),因为要求前 \(k\) 小,这一位可能多于 \(k\) 个数。
例题:
\({\color{purple} 40.冒泡排序次数}\)
一轮冒泡排序为枚举 \(i\) 从 \(1\) 到 \(n-1\),若 \(a_i > a_{i+1}\) 则交换。设 \(f_i\) 为 \(i\) 左边比 \(i\) 大的数个数,那么完成排序需要的轮数为 \(\max{f_i}\) 又等于当前下标减去其排名。
例题:
\({\color{purple} 41.树上最小连通块}\)
若有关键点集 {\(v_1\),\(v_2\),...,\(v_m\)},则树上包含这些点的最小连通块大小为 \(\frac{1}{2} \sum_i^ndis(v_i,v_{(i+1) mod m})+1\)。前提是点集已经按照 dfs 序排序。
例题:
\({\color{green} 42.任务选择}\)
第 \(i\) 个任务从 \(s_i\) 时间开始,需要花费时间 \(t_i\),同一时间只能做一个任务,则若当下空闲且有任务就去做,一定不劣。设 \(x\) 是最后一个在开始时间准时进行的任务,则最终做完任务的时间为 \(s_x-1+\sum_{j=i}^nt_j\)
例题:
P11861 [CCC 2025 Senior] 写作业 / To-Do List
\({\color{black} 43.值域分块+倍增}\)
当我们要对初始值和初始位置预处理一些信息,可是初始值域非常大,我们难以对于每个位置都进行预处理时,考虑把初始值比较相似的值放在一起处理,它们的大部分过程都是一样的,在很少的位置发生分歧的时候我们暴力处理。因为是重复的过程所以用倍增加速。
例题:
\({\color{purple} 44.prim 拓展顺序}\)
当边权互不相同的图做 prim 算法求最小生成树时,从任意起点开始得到的都是同一棵树,设 \(d_{s,i}\) 表示从 \(s\) 出发拓展到 \(i\) 时 \(s\) 的连通块大小。若要求 \(\sum_{s=1}^n d_{s,x}\),则可以在 kruskal 的过程中求出,边权从小到大枚举,考虑 \(u\) 对于 \(v\) 的 \(\sum d\) 有什么贡献,即 \(u\) 这一侧可能成为起点的点数乘以 \(u\) 此时的连通块大小,\(v\) 对 \(u\) 的贡献也同理。然后启发式合并,把小连通块合并到大连通块里,用标记永久化可以维护此时的答案。
例题:
P15455 [JOI 2026 SemiFinal] 新的桥梁 / New Bridge
\({\color{cyan} 45.子段 mex}\)
将一个序列划分成若干个 mex 相同的子段,则此 mex 等于全局的 mex。
例题:
\({\color{blue} 46.极小 mex 区间}\)
定义:对于一个极小 mex 区间 \([l,r]\),不存在 \(l \le l'<r'\le r\)且 \(l' \neq l\) 或 \(r' \neq r\),使得 \(mex([l,r]) = mex([l',r'])\)。
这样的极小区间数量级为 \(O(n)\)。
例题:
\({\color{purple} 47.迁移计划}\)
将树上深度为 \(x\) 的节点的点权分别转移到其深度为 \(y\) 的祖先,用线段树合并,询问点权求子树和。
例题:
P11993 [JOIST 2025] 迁移计划 / Migration Plan
\({\color{grey} 48.改变求和顺序}\)
推式子时若有 \(\sum_x \sum_df(d) \times a_x\) 之类的结构,考虑提出和 \(d\) 有关的项时,可以交换 \(x\) 和 \(d\) 的求和符号。
\({\color{green} 49.\sum 算术平均数}\)
一个序列所有子区间的算术平均数之和为 \(\sum_{d=1}^n \frac{1}{d}(ss_{n}-ss_{d-1}-ss_{n-d})\)。其中 \(ss_i = \sum_{j=1}^i s_j\),\(s_j=\sum_{k=1}^ja_k\)。
例题:

浙公网安备 33010602011771号