Tips
-
我们真的需要关心这个量吗?
-
需要维护序列,任意删除元素,末尾添加元素,可以用值域(开 \(V + Q\))动态开点线段树,带
vector可求答案。(列队) -
形如 \(a_i \gets a_{i-1}+a_{i+1}-a_i\) 之类的操作,相当于交换差分数组中的某两个元素。(方差、最小化和)
-
求两个排列的最长公共子序列,可以将一个排列排序再做。
-
一些神秘的暴力,可以观察有没有多余操作(有关值域等),通常是看看有没有【加倍】或【减半】,使暴力优化成 \(\log\)。
-
位运算拆位老套路。
-
和序列 \(A\) 中连续段有关的 \(\sum f(A)\) 题,可通过每个元素的【切割贡献】转化成普通计数。this.
-
构造题中给的带 $ \le \frac{1}{?} \cdot ...$ 的神秘条件,可以考虑构造出 \(?\) 种方案,总和是 \(...\),于是代价最小的方案的代价必然 \(\le \frac{1}{?} \cdot ...\),就是一组可行的解。this.
-
判定一条边是否能成为图上某两定点之间某路径第 \(k\) 大的,可以将图上大于该边的边权设为 1,小于等于的设为 0,跑最短路,看看最短路是否等于 \(k-1\)。
-
DP 时,如果状态数很多而结果的值域很小,不妨试试交换某一维状态和值域。
-
DFS 枚举【分组】的时候,可以尝试将状压后的还未分组的集合传参,每次递归的时候保证当前集合中第一个未分组的元素要被处理掉,这样常数很小。(由枚举每个元素分在哪一个组,并动态记录当前有几组进化而来)this.
-
需构造排列,可考虑随意构造两两不同的序列再离散化。
-
T1 级别的枚举题,而高次方枚举过不了的,考虑折半。
-
序列中【可达性】问题,可以考虑预处理每个点能达到的最前/最后点下标,贪心地判断。(如果后点能到达的最前点小于/大于前点,那么可行,因题而异)
-
DP 有的时候可以倒着搞。
-
树上两个结点没有祖孙关系,等价于其 DFS 序中管辖的区间不相交。
-
序列升序等价于差分数组最小值非负,单点修改、区间修改 set 可做。当然也可以用线段树维护两边最小值最大值。
-
网格图中间有一个连通块,要想判断一个回路是否把连通块包住,等价于从连通块中任意一点向任意一边引一条射线,回路经过这条射线奇数次。和判点在多边形内部很像。
-
点分治的另一个算贡献的写法:分治中心下所有点对,减去两个点在同一子树的情况。
-
基环树上拓扑排序也是一种思路。
-
贪心时,可以考虑一个临界的合法情况,再进行调整。
-
子串是后缀的前缀。
-
正者扫一遍,倒着扫一遍。
-
\(x=\sum_{i=0}^{+\infty} \left [x>i \right]\)。
-
经典的多米诺骨牌(\(1 \times 2\))覆盖 \(n \times m\) 矩阵,可以通过相邻黑白染色转化。
-
\(k\) 大值的技巧:二分、超级钢琴,以及直接枚举钦定 \(k\) 大值。
-
CDQ 要手法去掉相互贡献的情况。
-
动态问题可以用 CDQ 转成静态问题。比如,我们要实现一个结构,支持插入和查询。但是不特殊的插入是困难的,整段重构是简单的,而且每一个插入对询问是独立的。这时可以通过 CDQ 将动态问题转化成每一个插入进来的点,对后面的贡献,从而变成静态。
-
有加入、删除、查询,且删除是困难的,撤销是简单的,可以考虑线段树分治。
-
DP 不止能考虑【前 \(i\) 个点】,也能从值域的角度,从小到大 DP。
-
树形 DP 两个事:
- 由 \(u\) 为根的子树添加一个父亲。
- 由 \(u\) 为根的子树,其中有一些孩子已经转移,添加一个子树。
-
border 首尾都有一个。如果通过一些神秘的变换让他们在一起,就有可能出偶回文串。
-
DP 算所有可能的序列的总权值的题,不一定要从算【确定序列】的权值入手,可以考虑直接算总贡献。比如,考虑权值是某个值的序列有多少个,考虑一定情况有多少种序列会产生贡献,等等。
-
某一权值【恰好】等于多少的计数题,可以考虑变成【至少】,然后容斥。
-
二项式反演:先钦定,再任选,可认为是分步。
-
地图的范围比较大,但是横纵坐标有限,考虑扫描线。
-
关于 DAG 状压计数一个常见套路(必记!)是:钦定零度点集,简单容斥去重。
-
AC 自动机可以看成是两棵树拼起来:Trie 树和 fail 指针构成的树。
-
排列计数,但是状压:记 \(p_i\) 为 \(i\) 的一个映射。考虑设 \(f(S)\) 为 \(n\) 个元素满射至 \(S\) 的方案数。\(g(S)\) 为 \(n\) 个元素普通映射至 \(S\) 的方案数。可以去掉一些枚举子集的部分。(SDOI 小星星)
-
对于覆盖类问题,考虑区间 DP。
-
树的问题考虑链怎么做,再想怎么拓展。
-
分组计数问题,可以这么定义状态:\(f_{i,j}\) 表示,考虑到 \(i\),前面有 \(j\) 个空位没有填。转移就考虑这 \(j\) 个空位会被填掉还是保留。
-
发现每一种分组方案可以看做给一个 \(b\) 数组填数,表示 \(i\) 所在组的元素个数。那么分组就可以视为给每个 \(b_i\) 填一个 \([1,a_i]\) 的数。记 \(j\) 在 \(b\) 中出现了 \(t_b\) 次,一个 \(b\) 数组是有效的等价于所有 \(t_i\) 是 \(i\) 的倍数。
再考虑对于一个确定的 \(b\) 数组,贡献是什么。(一 \(b\) 对多方案) -
“乱向树”上的计数,可以先考虑有根的外向树和外向森林上怎么做,再考虑钦定一些反向边为割边,做带容斥系数的 DP。
-
两人博弈,一个想让答案大,一个想让答案小,可以用二分的方式思考,二分答案 \(k\),序列(或其他结构)中,\(\ge k\) 的数变成 \(1\),其他变成 \(-1\)(或 \(0\)),转化成普通的,胜负的问题。

浙公网安备 33010602011771号