总结复习

不知不觉已经两年 OI 了
主要是回顾一下以前做过的一些题目,
由于开始写这个玩意的时间比较靠后,所以漏了很多好题
慢慢加

基础算法

搜索

数论/数学

图论

字符串

  • Trie 树 http://www.fzoi.top/problem/4903 答题卡 手动模拟样例,转化问题成短串第一个字母外和长串后缀相同,第一个字母在长串之前出现过,trie 树上 dp
  • KMP 变形 P5256 JSOI2013编程作业 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 改变两个字符相等的条件:到上一个相同字符的距离相等,同时注意到上一个字符可能不在匹配范围内的判断
  • exKMP+Manacher http://codeforces.com/gym/101981 MEDIOCRE STRING PROBLEM 转化问题,\(S_1+S_2+T\) ,假设已知 \(𝑆\) 中每个位置拓展的最长回文半径 \(𝑝𝑖\) 那么对于半径 \(pi\) 的回文,对应的方案要求 \(𝑆1\)\(𝑇\) 对称,且 \(𝑆1\) 的右端点固定,把 \(𝑆\) 反过来做 exKMP 即可。注意到最后统计答案的时候,需要差分计算 右端点在 \(i\) 的回文串个数,否则答案会漏很多
  • KMP 循环节 Problem - 3746 (hdu.edu.cn) \(kmp\) 一遍后,最小循环节就是 \(n-kmp[n]\)
  • AC自动机+FAIL树上计算 NOI2011 阿狸的打字机 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 首先建出 AC 自动机和 \(fail\) 树,容易发现,对于一个询问 \((x,y)\) ,我们不妨让 fail 树的根到 fail 树上的 y 这一条路径上的点全部+1,那么 \(x\) 的重复次数便是 \(x\) 在 fail 树上子树中1的数量。这是因为如果 \(x\) 在 fail 树的子树上如果存在 1,假设这个节点是 z,那么由 fail 的性质,字符串 \(x\) 可以通过在尾部增加字符的方式变成 z,而 \(z\) 为 1,也就是说 z 是 \(y\) 的子串。需要注意的是,因为我们在得到 fail 数组的时候对原 trie 树进行了修改,所以我们最后在 trie 上 dfs 的时候需要在原 trie 的 copy 上进行,不然就会死循环(卡了我好久
  • 后缀数组+单调栈 [P4248 AHOI2013]差异 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 建立后缀数组后,考虑每一个 \(height[i]\) 对答案的贡献。知道对于排名分别为 \(i,j\) 的两个字符串,最长公共前缀为 \(\min_{l<k\leq r}\{height[k]\}\)
  • AC自动机+栈 「USACO2015FEB」Censoring (Gold) - 题目 - FZUOJ (fzoi.top) 注意到我们求解 \(fail\) 的时候有一个对 trie 树进行修改的操作,这个操作实际上与 \(kmp\)\(next\) 数组类似。考虑开一个答案栈,把 S 放进 AC 自动机里面跑,匹配就退栈即可
  • AC自动机+DFS找环 POI2000」病毒 父节点到子节点看作一条单向边,失配指针nxt[]指向的也看作一条单向边,最后会形成一个图。 如果在这个图中找到一个环,且不存在结束标记,那么存在一个以环为循环的无限长的安全代码。 注意:如果一个点的 fail 指向的位置有结束标记,这个点即使没有结束标记也需要加上结束标记
  • AC自动机+DP 「JSOI2007」文本生成器 注意到 \(fail\) 树的传递性质。用所有的情况减去不可读的情况(跑不到单词结尾节点的情况)。不可读的情况数量可以用 d p 求。设 \(f[i][j]\) 表示匹配了 i 个字符,现在到 j 号节点的不可读情况数量,从父亲往儿子转移。
  • Manacher 「POI2010」Antisymmetry - 题目 - FZUOJ (fzoi.top) 修改字符相同的定义即可,每一个 i 的贡献为 \(p[i]/2\)
  • KMP [POI2006]OKR-Periods of Words 画图观察,容易发现 KMP 性质。
  • KMP+DP 「CF432D」 Prefixes and Suffixes - 题目 - FZUOJ (fzoi.top) 题目要求的相同前后缀有明显的 KMP 味道,考虑计数,设以 \(i\) 为结尾的“完美子串” 出现 \(f[i]\) 次,有刷新: \(f[kmp[i]]+=f[i]\) ,注意应该倒序刷新
  • EXKMP [CF126B]Password 通过 exkmp,求得 z 数组通过 z[i]+i==len判断出这个串既是前缀又是后缀 ,maxn记录当前最大的 z,如果说我们已经找到了一个后缀前缀,并且在 i 前面的最大的 z[x] 是要比 n-i 长的,说明在中间至少也出现了一个相同的。求出最大的 \(i\) 满足 \(z[i]+i=n\) 并且 \(\exist j<i,s.t.z[j]>=n-i\) ,答案即为 \(s[1..z[i]]\)

数据结构

动态规划

  • 线段树辅助DP PYB 的字符串 - 题目 - FZUOJ (fzoi.top) 在序列没有修改的时候,我们设 \(f[i][j][k]\) 表示原串前 i 个字符,匹配串的 [j,k] ,可以不连续地出现次数。有修改,线段树区间合并,\(f[i][j][k]=f[l][j][k]+f[r][j][k]+\sum f[l][j][h]\times f[r][h+1][k]\) \(l,r\) 表示左右区间。求答案时,合并这 \(log\) 个区间即可。

  • 决策单调性 20211005 购票方案(VanishD day1) - 题目 - FZUOJ (fzoi.top) 容易得到方程,容易发现排序后存在决策单调性

  • 正难则反 20211005 直线相交(VanishD day1) - 题目 - FZUOJ (fzoi.top) f_(i,j)表示当前考虑了前i根木棒(前i根木棒和后面的都不平行),是否可以构成j个交点。转移:枚举最后一组平行的木棒数量k。则有方程:

    f_(i,j)=⋃_(k=1)^i f_(i-k,j-(i-k)×k) O(N^4)

    逆向DP 考虑当前的方案与最多的交点数(即全部两两相交相差的数量)那么将所有的木棒分成k组,每组内部都是互相平行的。数量为:a_1,a_2,…,a_k g_i表示与全满的状态相差i个交点至少需要多少木棒:

    $g_i=min_{j=1}^N⁡(j+g_{i-j×(j-1)/2}) $

    此时DP的时间复杂度为O(N3),考虑询问(N,M),他能完成当且仅当g_(N×(N-1)/2-M)≤N。总复杂度为O(N3+Q)

  • 容斥 20211005 记录数列(VanishD day1) - 题目 - FZUOJ (fzoi.top) 令sum_i表示存在至少i个相邻的区间能合并成更大区间的方案数 ans=∑_(i=0)^N sum_i×(-1)^i

    记 f_(i ,j,0 or 1) 表示考虑完第 i 段,存在至少 j 个相邻的段是可以接上的(即可以被看做一个更大的段),第 i 段序列是单调增的 0 还是单调减的 1。特殊处理 a[i]==1 的情况

  • 数据结构+决策单调性优化dp 20211005 模式匹配(VanishD day1) - 题目 - FZUOJ (fzoi.top)\(dp[i]\) 表示前 i 个字符可以构成的长度,\(dp[i]=max(dp[i-1],dp[k]+4)\)\(k\) 满足 s[k+1] 在区间 (pre[i],i] 中出现过。显然,k 越大,dp[k] 越大,决策单调性。考虑维护 k 的位置,考虑在从 1 遍历到 n 的过程中,维护 pre[] ,并把每一个 [pre[i],i] 在线段树上加上 i。线段树维护最大值,k 就是线段树在 pre[i]-1 的最大值对应的位置。特殊在于 aaaa 满足条件,需要跳一位再询问。

  • DP套DP [HDU 6968]I love exam - 题目 - FZUOJ (fzoi.top)\(A[i][j]\) 表示第 i 门课,花费 j 天的最高提分,\(B[i][j][k]\) 表示前 i 门课,花费 j 天,挂掉 k 课,最高得分。 A 显然是一个背包,B 通过 A 转就可以了。在做 A 的同时,需要记录 \(cost[i]\) 表示第 i 门课不挂科的最少用时,以判无解

  • DP辅助DP [P7914 CSP-S 2021] 括号序列(民间数据) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) [CSP-S 2021] 括号序列 题解 - lost_heart_hurts - 博客园 (cnblogs.com)

  • 状态结果交换 20211026 String - 题目 - FZUOJ (fzoi.top) 普通的,设 \(dp[i][j]\) 表示 \(a\) 匹配到 \(i\) 位,\(b\) 匹配到 \(j\) 位的最小步数,可以 \(O(|\sum|\ n^2)\) 解决问题,但是本题 \(n=5000\) ,需要干掉字符集。考虑设 \(f[i][j]\)\(i\) 表示长度 ,当前 \(a\) 串上匹配到 \(j\)\(b\) 串上匹配最多能到哪。 注意到出现最少的字母至多出现 \(n/26\) 次,所以答案不超过 \(n/13+1\)。所以暴力转移(每次 )复杂 度就是严格 \(O(n^2)\)

  • 树形DP 20211102 查询工资(lookup) - Problem - FZUOJ (fzoi.top)

  • 前缀和优化DP 20211102 多项式题(poly) - Problem - FZUOJ (fzoi.top)\(dp[i]\) 表示在 \(i\)\(i+1\) 之间截断,前面任意的答案。

  • 单调队列优化DP 20211101 电梯(elevator) - Problem - FZUOJ (fzoi.top)

  • 斜率优化DP [CEOI2017]Building Bridges 李超线段树维护,见题解

  • **树形DP ** 20211106 集合 - 题目 - FZUOJ (fzoi.top)\(B/F/C[x][k]\) 分别表示 \(x\) 子树内经过 \(k\) 个点(包含 \(x\) )的路径,起点终点都在 \(x\)/ 起点在\(x\) / 起点终点都不在 \(x\) ,转移即可(多画图!)

  • **数据结构优化 DP ** 序列(sequence) - 题目 - FZUOJ (fzoi.top)

  • 高斯消元期望DP 【HNOI2013】游走 考虑把边经过次数的期望转成点经过次数期望,点期望列出方程后直接高斯消元求解

  • 矩阵加速转移DP CF1151F 设 \(dp[i][j]\) 表示进行 \(i\) 次操作,最前面 \(m\) 个数中有 \(j\)\(0\) 的方案数,其中 \(m\) 表示全局 \(0\) 的个数。那么答案即为 \(dp[n][m]/\sum dp[n][i]\) 。发现转移方程可以写成矩阵。

  • 前缀和优化DP AGC009C ,不妨设 \(A>B\) ,那么无解情况就是 \(\exist a[i]-a[i-2]<B\)

    \(dp[i]\) 表示做到位置 \(i\) , \(i\)\(A\) 集合方案数,发现 \(j\) 若满足 \(\forall k\in[j+1,i],a[k]-a[k-1]\geq B\)\(a[i]-a[j]\geq A\) 即可转移到 \(i\) ,发现这样的j在一段连续的区间。前缀和优化。最后用dp[i]计算出最终答案

  • 容斥DP ARC101E Ribbons on Tree 设 \(f(S)\) 表示 \(s\) 集合中的边不染色方案数, \(g[i]\) 表示 \(i\) 个点两两配对染色方案数,F(S) 也很好计算, 显然 S 将原树分割成了若干个连通块, 我们只要把联通块大小对应的 g 值相乘就可以得到了,经过简单的容斥后可以得到 \(ans=\sum_{S\subseteq E}(-1)^{|S|}F(S)\) 。发现 \(f\) 的转移方式满足树形背包 DP 的形式,考虑设 \(dp[i][j]\) 表示在子树 i 内有 j 个点与 i 在同一个连通块的子树内匹配的方案数, 特别的, 令 \(dp[i][0]\) 表示子树 i 的点全部匹配的方案数,\(N^2\) 转移即可

  • 交换答案状态 20211115 跑步 - 题目 - FZUOJ (fzoi.top) 省略

  • 前缀最大值优化DP tree - 题目 - FZUOJ (fzoi.top) 首先小心可能直径不经过环。考虑在环上 DP ,发现一个点可能可以和前面的组合,可以和后面的组合,也可以换个方向绕一圈,容易发现可以前缀最大值优化。

计数

  • 条件转化 [2021牛客提高第一场]与巨 - 题目 - FZUOJ (fzoi.top)
  • 计数DP [P2051 AHOI2009]中国象棋 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 按行考虑,设 \(f[i][j][k]\) 表示前 \(i\) 行,\(j\) 列填了一个棋子,\(k\) 列填了两个棋子的方案数
  • 计数DP+刷新 [P5456 THUPC2018]蛋糕 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 发现每个维度相对独立,且当且仅当当前维度坐标达到上/下界接触面增加1。设 \(dp[i][j]\) 表示前 i维,接触了j面的方案数,讨论维度上界是否为1即可。这里需要采用刷新的方式。
  • 差分转化计数 [HDU 7055]Yiwen with Sqc - 题目 - FZUOJ (fzoi.top) 推狮子发现存在平方项,不好动态维护,考虑差分降次
  • 树上计数 「NOIP2014」联合权值 - 题目 - FZUOJ (fzoi.top) 容易算出每一个中转点的贡献
  • 条件转化+递推 基础计数练习题(perm) - 题目 - FZUOJ (fzoi.top) 发现 P>Q 和 P<Q 的方案数是相同的,那么 \(v[i]=\frac 12 (i!-f[i])\) ,其中 \(f[i]\) 表示 \(1\)\(i\) 的排列,st,P=Q 的方案数。容易推得: \(f[i]=f[i-1]+(i-1)\times f[i-2]\) ,即形成 \(p_x=x\) 或者 \((p_x=y,p_y=x)\) 的二元组。
  • 抽屉原理 CF850A Five Dimensional Points - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 发现五维坐标有 5 条坐标轴,然后知道每个坐标轴分 + and - 所以我们任意将一个点作为坐标原点,这样知道当 n > 34 时一共有 33 个其余的点。根据抽屉原理,这样就至少有一个象限分到两个点。然后如果真的有的话,那么无论如何当前这个坐标原点所对的点不能成为“好点”。根据抽屉原理,知道当 n > 34 时答案永远是 0。
  • 计数DP ABC226F 见题解
  • 图上计数 20211108 黑白树 - 题目 - FZUOJ (fzoi.top) 考虑把直径提出来,对于普通的树,到一个点最远的点一定是直径的端点之一,先求出一条直径,若直径的两个端点颜色相同, 则最长距离一定为直径,否则,令两个端点分别为 x, y,枚举答案 d,所有到 x 距离 > d 的点颜色必须与 y 一样,所有到 y 距离 > d 的点颜色必须和 x 一样,由于 x, y 是直径的两个端点,可以发现,若一个点 z 到 x, y 的距离都不超过 d,则其到任何一个点的距离不超过 d,所以 z 的黑白并不会对答案产生影响。 具体的,找出直径,预处理直径到每一个点的距离,从大到小枚举 d,维护当前没有被限制的点的个数, 当出现 min dis(x, i), dis(y, i) > d 时说明 d 已经不合法。

构造

  • 分块 20210925 不等(pb day1) - 题目 - FZUOJ (fzoi.top) 如果没有 01 数量不相等的限制,那么直接令颜色等于 bitcount 的奇偶性即可。根据 \(\lceil \sqrt{n}\rceil\) 的提示,可以想到用分块的方式调整数量。可以找到这样一个函数: 把 \(n\) 分成 \(\sqrt n\) 块,那么一个 \(n\) 位二进制数的函数值是 1 ,当且仅当它至少一块全都是 1。我们让最后的颜色变成 奇偶性 \(\oplus\) 函数值,那么, 一个函数值是 0 的数只有 \(\sqrt n\) 块可能变成 1 ,每块都至多一种方案,所以函数值为 0 的数只有 \(\sqrt n\) 种方法会变化;而 一个函数值为 1 的数只有在只包含一块的情况下会变,此时这个块长也是 \(\sqrt n\)

  • 奇偶分析 CF550D Regular Bridge - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) •由于是无向图,所以子图的总度数应为偶数。所以n和k都是奇数 。由于每个点的度数为k,所以一张子图至少要k+1个点,但k+1奇偶性不对,所以我们考虑k+2个点。将完全图删去(1,2),(1,3),(4,5),(6,7),…,(k+1,k+2)即可。

  • 贪心 [AGC010E] Rearranging 每个整数建一个点,不互质的连边。显然可以每个连通块求出答案后贪心合并。对于一个连通块,第一个数可以取最小的(记为x)。接下来考虑删去它之后的每个连通块,为了使x不被换到后面,每个连通块的第一个数必须是与x有连边的。同样每个连通块求出以后合并即可。

  • 树分块 [SCOI2005] 王室联邦 一个有效的构造是,递归处理每个点,每次把当前节点假如栈中,对于扫过每个儿子,看现在栈中的点个数是否 \(\ge B\) ,是则分块。这样,子树中最多遗留 \(B-1\) 个点,和另外一个子树一起,算上父亲,最多 \(2B-1\) 个点。dfs 结束后,可能栈中还剩下 \(B-1\) 个点,假如根节点所在的块中,大小 \(\leq 3B\)

posted @ 2021-11-19 11:59  _Famiglistimo  阅读(289)  评论(0编辑  收藏  举报