DP专场
CF1814E Chain Chips
好久没写这种题了~~
不带修时,为了让总距离和最短,考虑让相邻的车互换位置,但如果单纯这样有可能剩下一辆车,那就让相邻的三辆车换一下。发现当车的个数 \(x \ge 4\) 时,都可以拆成 \(2\) 辆或 \(3\) 辆车。对应到边就是只能选相邻的一条边或两条边。设 \(dp_i\) 表示第 \(i\) 条边必选且满足条件的答案,那么:
利用加法对取 \(\text{min}\) 操作的分配律,转化为广义矩乘递推:
用线段树维护支持修改。
CF1774E Two Chess Pieces
考虑每个棋子必须经过哪些点:
- 子树里有己方标记点的点
- 与子树中对方最深标记点距离大于 \(d\) 的点
除根结点外每个需经节点贡献为 \(2\),一遍 \(\text{dfs}\) 解决。
虚假的 \(\text{dp}\),真实的贪心
CF1763D Valid Bitonic Permutations
看到数据范围都很小啊,考虑枚举拐点 \(\text{id}\) 在哪个位置。首先有个很容易被忽略的隐藏条件(也有可能是我比较逊没想到),拐点的数值必是 \(n\)。然后拐点在每个位置的贡献就可以暴力分为 \(6\) 类:
除了中间两类(拐点不在中间的时候)都很好理解啊,考虑拐点在中间的情况,以 \(x < y\) 为例。先把一定不冲突的选掉,即 \(\text{id}\) 到 \(j\) 中间的与 \(i\) 之前的。剩下比 \(x\) 小的必然放在 \(j\) 右边,再把比 \(y\) 小的剩下数选一些填满 \(j\) 的右边,最后剩下的数排在 \(i\) 和 \(\text{id}\) 间。
真实的数学,虚假的 \(\text{dp}\)
CF1762F Good Pairs
如果直接从一个位置 \(a_{i_x}\) 往前找和它差的绝对值不超过 \(k\) 的位置并直接转移,用线段树维护发现会算重。
但其实有这样一个事实,当 \(a_{i_{x-2}} \le a_{i_{x-1}} \le a_{i_x}\) 时,其实可以直接从 \(a_{i_{x-2}}\) 转移到 \(a_{i_x}\)。于是所有可选序列都可以被缩成单调不降或单调不增的。
考虑只考虑单调不降的,反过来再做一遍,再把全相同的算重的部分减掉。
设 \(dp_i\) 表示当当前右端点 \(r\) 为 \(i\) 时左边合法的 \(l\) 个数。找到 \(i\) 左侧满足 \(a_j \le a_i\) 并且 \(|a_i-a_j| \le k\) 的第一个 \(j\)。满足条件的 \(l\) 可以被分为三类:
- 在 \(j\) 和 \(i\) 之间 \(l\) 的必然不满足。
- 在 \(j\) 左侧且值域在 \((a_j,a_i]\) 的 \(l\) 都可转移到 \(i\)。
- 在 \(j\) 及其左侧且值域在 \([1,a_j]\) 的 \(l\) 都直接通过 \(dp_j\) 转移。
用线段树维护即可。注意每次不能暴力建树,做一遍反操作清空。
CF1840F Railguns
设 \(dp_{t, i, j}\) 表示在第 \(t\) 秒在 \((i, j)\) 是否可行。则:
第一维可以滚动数组,后两维可以压成一维。
CF1843F2 Omsk Metro (hard version)
发现树上一条路径 \(x \to y\) 一旦建立,由于没有撤销操作,这条路径就固定不变了。于是把整棵树建好,把询问离线下来,就是一个静态问题了。
由于点权值域为 \({-1, 1}\),一条路径的上每拓展一个节点其权值和在整数域上是连续变化的,故只要求一条路径的最大子段和与最小子段和,看 \(k\) 是否在这个区间即可。
具体的用倍增实现,在 \(\text{lca}\) 处合并时要把其中一条链翻转一下,注意空串和为 \(0\)。
CF1827C Palindrome Partition
CF1750F Majority
有一位伟人告诉我们:正难则反
这题的 \(\text{dp}\) 状态设置非常巧妙,满足条件的方案数等于总方案数减去不满足条件的方案数。当一个串的两端都为 \(1\) 时,对于不满足条件的方案,完成所有可行的操作后,必然形成 \(01\) 相间的串,且首尾均为 \(1\) 串。设 \(dp_{i, j}\) 表示可行操作结束后长度为 \(i\) 的左右两端均为 \(1\) 的最右端为长为 \(j\) 的 \(1\) 的串包含的方案数。
于是对于 \(dp_{i, i}\) 有:
对于 \(dp_{i, j}(j < i)\),考虑在末尾的 \(1\) 串左边添一个长为 \(k\) 的 \(0\) 串,再接一个末尾为长为 \(m\) 的 \(1\) 串的串。所以:
其中 \(dp_{n, n}\) 即为答案,暴力计算为 \(O(n^4)\)。内层的求和显然可以前缀和优化,外层的求和为第一个前缀和矩阵上的斜前缀和,优化后为 \(O(n^2)\)。