做题策略
寻找充要条件
很多题我们需要转化题意,无论是换成代数形式,还是简化模型,我们都需要抓住充要条件。
下标和值域的转化
这个在数据结构很常用。
这道题直接做不好做,所以我们考虑在值域上面做。我们把 放在数轴上排序,然后我们利用双指针维护可行的区间,最后答案就是最小的。
动态规划 dp
概率论逆序对
表示 位置上大于 的概率()。
数据结构优化
可以用线段树维护可行区间的区间最小值进行快速转移。CF1557D Ezzat and Grid。
数据结构
树状数组
树状数组二分
P6619 [省选联考 2020 A/B 卷] 冰火战士。我们发现树状数组一个点 存储了 的所有信息**,所以我们在树状数组上二分,像倍增一样,从大到小依次枚举这个点加上 的祖先,如果能跳就跳。从高位到低位,从 now 尝试跳到 k = now | (1<<j) 时,由于二分是从高位到低位构造的,此时 lowbit(k) 恰好等于 1<<j。
线段树
pushup 优化
这个是一个很神奇的优化,P4198 楼房重建。我们考虑优化 pushup 使其做到 。
遇到一些问题,区间外的一些会影响区间内的时候,我们就需要利用这个 trick 优化我们的算法。这个问题很大可能是一个有关 的一个问题,我们可以通过 所处位置进行分类。本质上是每一个节点的计算只需要进入 左儿子/右儿子。
代码
int get(int x,int l,int r,double mx){
if(t[x].mx<mx)return 0;
if(l==r){
return t[x].mx>mx;
}
if(t[ls].mx<=mx)return get(rs,mid+1,r,mx);
return t[x].res-t[ls].res+get(ls,l,mid,mx);
}
void pushup(int x,int l,int r){
t[x].mx=max(t[ls].mx,t[rs].mx);
t[x].res=t[ls].res+get(rs,mid+1,r,t[ls].mx);
}
区间计数问题
求 的个数,转化成 ,也就是维护 最小值的个数。
值域小的问题
对于每一个字母开一颗线段树,然后按照顺序处理。很多时候这样是可行的。
两个维度的问题
可以主席树,本质就是一个维度维护了差分版本信息,另一个维度维护值域。
和位置关系不大的题目考虑值域。
分治解决子区间最大问题
子区间最大值问题可以考虑分治。
与两个此消彼长的,例如值域与个数有段的问题
和数字值,个数的东西有关的可以想想根号分治。
价值求和问题
二分第 大区间的值。
CF1034D Intervals of Intervals。真的很神奇。
有关 tag 的
注意:
- 有翻转赋值 tag 赋值优先级高。但是有赋值也可以有后面的翻转。
图论
LCA
LCA 的深度
和 的 LCA 的深度就相当于把 到根结点的路径填成 ,然后问 到根结点的路径的权值和。P4211 [LNOI2014] LCA。
最短路相关
双向多源 dij
让关键点作为源点,然后两个方向都 dij 一遍,最后就可以寻找出最短路径了。[GXOI/GZOI2019] 旅行者。
最大/最小的限制模型
直接同余最短路就可以了,可以进行限制。关于 和 的计数有时也可以,比如 CF1473E Minimum Path,我们发现减去的是最小值,加上的是最大值,所以我们可以想到对于没一条路径,我们需要让其权值更小,这让我们想到了分层图最短路,是否已经决定了最大/小值。
带有很多点的点集
这种点很多的题目我们可以考虑 LCA。我们考虑点集的 LCA 和加上特殊点的。P6071 『MdOI R1』Treequery。
二分图判定
判断二分图的充要条件是没有奇环,可以用扩展域并查集判断。
矩形包含问题
一个点向右做射线,与图形竖线的交点个数为奇数的时候,这个点在这个图形里面。射线不要和边线重合。
欧拉定理
定理公式:
代表顶点数, 代表棱数, 代表面数。
数学
计数
突破口
- 找到范围很少的量。CF559C Gerald and Giant Chess,这道题的黑格。
高斯消元求概率
CF113D Museum。P3211 [HNOI2011] XOR和路径。
由于这一类问题的转移是无限的,所以我们需要把转移列成方程,然后利用高斯消元解出来。
前者需要设两点的位置为一个状态。
一般有两种设法:
- 设一个位置经过的次数。从 正着转移。
- 设一个点经过的概率。从 倒着转移。
gcd 计数
最常见的逻辑:直接枚举 gcd 的值,反演或者普通计数都用得到。
枚举 ,然后 是为 的倍数的贡献, 是为 的贡献。
拆分技巧
可以转化成等差数列。
拆分问题
有二进制拆分,相对应的,也有质因数分解拆分,将问题让每一个质因数做一遍。AT_arc192_d [ARC192D] Fraction Line。
容斥
子集容斥
这应该是一个很重要的模型了。
P3349 [ZJOI2016] 小星星。如果设类似 的这种状态来转移,转移的时间复杂度是 的,这个可以用容斥优化。我们直接钦定整个转移过程中的集合是 ,最后容斥一下,就能得到恰好是 的了。
反射容斥
CF1204E Natasha, Sasha and the Prefix Sums。我们发现对于一个 ,就相当于图上的路径需要和 有交点。如果起点终点在直线两侧,答案就是总数。如果不在同一侧,我们就要“反射”一下,这样并不会影响重点哦。然后现在上移了 步,下移了 步。然后我们又可以求出总数了。
数论
降幂/拆根号技巧
同时 ln
左右同时 :
原根
神秘的降幂方式:用原根。CF1106F Lunar New Year and a Recursive Sequence。
博弈论
SG 函数
SG 值就是下一个状态的 mex,多个起点就把 SG 异或起来。
只要状态转移跟选手是谁无关就行了,这个可以直接得到,也可以转化得到。
bitset 优化:对于一个 sg 值维护拥有 TA 的下标。CF1091H New Year and the Tricolore Recreation。
计数
考虑维度
对于排列计数,有两种方法,从位置考虑,从值域考虑。
字符串
- 好吧,很多难的字符串题可以用哈希做。。。
AC 自动机
AC 自动机上 dp
:长度为 ,在 AC 自动机节点 的最大得分。
P3041 [USACO12JAN] Video Game G。P4052 [JSOI2007] 文本生成器。
fail 树
我们可以每一个点的 fail 都是这个点的父亲,然后这棵树的性质就是每一个点如果在序列出现过,其父亲链上的所有的一定都出现过。
kmp
Border Theory
所有 border 长度构成的序列,可以划分为 个等差数列。
字符串循环节
直接 就是一个循环节,因为可以一一对应上。CF432D Prefixes and Suffixes。
Height 数组
lcp
构造
黑白格
AT_agc027_d [AGC027D] Modulo Matrix。
白格质数相乘。
ad-hoc
缩小范围
拆分一个序列长度的种数一定是根号级别的
这种 一定第根号级别的。
排序
a+b 和 b+a 比较
这个是一个很厉害的性质呢。P1012 [NOIP 1998 提高组] 拼数,结论是比较 和 ,证明方法:
证明
\tag{A} \frac{a}{10^m-1}>\frac{b}{10^n-1}
\tag{B} \frac{b}{10^n-1}>\frac{c}{10^r-1}
\tag{C} \frac{a}{10^m-1}>\frac{b}{10^n-1}>\frac{c}{10^r-1}
二分 01 排序
P2824 [HEOI2016/TJOI2016] 排序。因为只问一个数,可以直接二分 ,只需要把 的设成 ,看最后这一位是 还是 , 排序线段树维护。
贪心
Exchange Argument
这个是一个思想,就是贪心地进行排序。
比如 AT_agc023_f [AGC023F] 01 on Tree。 设节点 所在连通块的 个数分别为 ,那么如果 排在 前面,跨过连通块的贡献为 。也就是说, 排在 前面更优的条件是
即
P4437 [HNOI/AHOI2018] 排列 这个也比较像。