板子复习
三分
注意你的目标函数必须是严格单峰的,途中不能出现平着的一段。
大体思想就是取两个三等分点。
KMP
先求出 \(\pi\) 函数。
注意完全匹配上了之后要强制让 \(j=\pi_j\)。
笛卡尔树
考虑从左往右挨个加数,维护一个一直往右的右链,每次暴力往上找即可。
欧拉路径
首先有向图存在欧拉路径的充要条件是所有点都入度=出度,或者存在恰好一对点,一个入度比出度少 \(1\),另外一个相反。
对于前者可以随便选一个点当作起点;对于后者则必须选入度比出度少 \(1\) 的那个。
考虑构造一条路径。考虑每次找到一个环,然后以环上每个点作为起点继续找环。容易发现这样一定可以。
那更简单的做法是什么呢?考虑在对环回溯的时候找环。最后把整个序列 reverse,就得到了欧拉路径。
为什么正着走的时候直接找不行呢?很显然你回溯的时候经过的不是边,而是反的边。
连通性相关
你真的搞明白连通性了吗?
OI 中我们常用的连通性算法有 SCC、ECC、VCC、割点、割边。
而这些都基于 DFS 算法。通过分析 DFS 的非树边类型,就可以求解上述问题。
在这些算法中我们都定义了 \(\operatorname{dfn}_u\) 和 \(\operatorname{low}_u\)。然而大家可能会有一个疑问:为什么在非树边时 \(\operatorname{low}_u\) 要对 \(\operatorname{dfn}_v\) chkmin,而不是 \(\operatorname{low}_v\) 呢?
经过一些测试可以发现,只有点连通性相关问题需要 \(\operatorname{dfn}_v\)。为什么?考虑一个图:
1---2---3---5---6
\ / \ /
4 7
如果不严格指定只能走一条非树边,那么 \(\operatorname{low}_6=1\),而这会导致 \(\{5,6,7\}\) 不能被判定为一个点双。显然会出错。
根本原因在于,走一条非树边可能会走到这个点双的根节点,而再走是不行的。
SCC:P3387。
注意需要记录一个点是否在栈中。在才能转移。这是显然的。因为这是有向图,所以只有返祖边才有用。
ECC:P8436。
注意记录的是入边的编号,而且邻接表要从 \(2\) 开始存。这里就不用必须是返祖边,所以不用记录一个栈。
割点:P3388。
注意要对 \(u\) 为搜索树的根特判。
VCC:P8435。
注意这里也要记录一个栈,是为了快速找到一个点双里的所有节点。当然如果你边双想这么写也没问题。
注意一个孤立点的情况。注意孤立点上有自环是没用的。(实际上自环根本就没用)
注意弹栈的时候判的是栈顶不等于 \(v\),最后别忘了把 \(u\) 加进去。
Manacher
要处理长度为奇数和偶数的回文串,比较恶心。可以考虑每隔一个字符插入一个分隔符,最后在开头和末尾插入两个不一样的字符。这样只需要统计长度为奇数的回文串。
有人认为这样常数太大了,实际上完全没有影响。就算你算两遍那也还是两倍常数。
核心思想是维护一个最靠右的回文串,每次暴力往右扩展复杂度是对的。
差分约束
转化之后是单源负权最短(长)路问题。
可以使用 SPFA 解决。注意判负环时,要考虑超级源点,点个数是 \(n+1\)。
Johnson 全源最短路
复杂度为 \(O(nm\log m)\)。
大概是先用 SPFA 跑出来一个势能。然后在这上面跑 Dijkstra。
需要注意的是判负环时,要考虑超级源点,点个数是 \(n+1\)。
单侧递归线段树
核心思想在于 pushup 需要的信息是由线段树上二分给出的。
需要注意贡献的情况。

浙公网安备 33010602011771号