拿到一道题,先审题:
题目中会有关键的语句,提示你往哪里想。
“询问最大……的最小值”“最小……的最大值”(前者更常见一些) : 考虑二分
棋盘格子,尤其是涉及“相邻”的操作的: 考虑黑白染色跑网络流
对于一个森林,考虑建立一个虚点,把它变成一颗树
对于按指定顺序balabla……,有时考虑倍增
对于一些依赖时间的情况,比如第\(i\)条路在时刻\(i\)开放,或者后来的会覆盖先来的,可以考虑直接倒序枚举,离线处理询问
二分:
可能直接二分答案,也可能二分一个与答案有关的值。
满足单调性的基本都能二分,例如,若……随时间增加单调递增,或者随位置增加单调不降,就二分那个自变量就好了
证明单调性有时候可以感性理解,即“若x成立,x+1一定成立”“x不成立,x-1一定不成立”,如果能证出类似这些的东西,就可以暂且认为它有单调性
二分的时候,不要在值域上二分,可以把值域范围优化到n进行二分。因为答案必然是题中出现的数,所以可以令l = 1, r = n,原数组排序后在数组中二分,这样在check中枚举的时候也不必每次都1-m枚举
容斥:
当出现“至少选一个”等形容时,即若AB均合法,可以选A,或选B,或都选……时,我们发现正着dp很难转移,这个时候可以考虑正难则反,转移一个都没有的方案,再用全集减去它
记得求容斥系数,可以选一个极端情况来求
dfs:
树上dp。倍增。lca。
如果一个点,能对它的答案造成影响的有且仅有它的祖先,可以考虑先搜索再回溯
判断点与点的祖先关系可以考虑欧拉序
有时要考虑换根dp,尤其是时间复杂度比较奇怪的时候
树上背包。树上差分。
DP:
如果有想不出来的题,往dp、递推上想一想
状态,决策,转移方程
状态一定要确保唯一,即当几维的值都定下来之后,对应且仅对应一个情况
先想暴力,再想优化达到正解
考虑循环顺序、预处理
网络流:
看到网格,尤其是和相邻格子相关的,考虑黑白染色,建图,白连源黑连汇,然后建图
判断可不可行,合不合法,可以看最大流能不能跑满,即等不等于预定的答案
不属于集合a就属于集合b,考虑最小割
满足某个条件的基础上要求……最小,考虑费用流
搜索剪枝:
在不合法的第一层统计答案,不要在最后一层统计答案
一些性质:
重心性质:
每个子树大小小于等于树的一半
在根节点所在的重链上
若有两个重心,则必然相邻