「Log」做题记录 2023.11.27-2023.12.31

\(2023.11.27-2023.12.3\)

\(\color{black}{P6965}\)

2-sat 是显著的。

对于无问号串,直接否定向自己连边即可,然后塞到 Trie 树里。

Trie 树上用子树、路径前缀优化建图即可。

\(\color{blueviolet}{P4334}\)

圆方树,点是显著的,割边转换为对应方点即可。

\(\color{blueviolet}{CF855C}\)

DP 即可。

\(\color{blueviolet}{CF678E}\)

枚举状态、当前擂主是谁,简单转移即可。

\(\color{blueviolet}{CF1158B}\)

神秘构造。

\(\color{limegreen}{P9166}\)

简单模拟,从 \(x\) 所在段向两侧扩展即可。

\(\color{royalblue}{CF449D}\)

首先考虑总方案数减去不合法方案数,枚举 \(1\) 的个数进行容斥。

于是需要求 \(val_{st}\) 表示包含状态 \(st\) 的数一共有多少个。

现在设状态 \(a \supsetneq b \supsetneq c\),并且 \(a\) 状态比 \(b\) 状态在 \(x\) 位上多 \(1\)\(b\)\(c\)\(y\) 位上多 \(1\)

考虑 \(a\) 的贡献加到 \(c\) 上的方式,先去掉 \(x\) 和先去掉 \(y\) 的贡献路径是等价的,所以我们钦定先去掉较小的位,这样不会重复。

\(\color{royalblue}{CF476E}\)

考虑删除一些位一定是为了匹配成一个串,否则杂乱的删除一定不优。

\(g_i\) 表示以 \(s_i\) 为开始字符要向后匹配到哪里可以出现一个完整的串 \(p\)。(可以不连续的,在 DP 过程中考虑删除其中的无用字符。)

\(f_{i, j}\) 表示当前匹配到串 \(s\) 的第 \(i\) 位,删除了 \(j\) 个字符最多能匹配完成的次数。

转移是简单的,要么继承之间的值,要么从当前位向后寻找一个串完成匹配。

\(\color{royalblue}{CF455C}\)(\(\color{blueviolet}{P2195}\) 双倍经验)

没啥水平题。

考虑两棵树连起来一定是将两棵树直径中点连起来,然后直径构成是显然的三部分,直接维护即可。

连通性的话放一个并查集即可。

\(\color{royalblue}{CF732D}\)

考虑直接二分答案,然后取出每个科目最后的考试时间,这样考试表固定,就可以贪心判断。

值得注意的是,很有可能某一科目在过程中没有出现。

\(\color{royalblue}{CF799C}\)

分类讨论,首先是一种买一个,直接取最大就行,考虑同种买两个的情况。

处理一个 \(f_i\) 表示用至多 \(i\) 元钱买一个得到的最大、次大价值,然后枚举钦定要买的物品,用剩余的钱买最优的即可。

\(\color{blueviolet}{CF487B}\)

没啥水平。

暴力 DP 是显著的,可以用单调队列维护区间最值,有决策单调性所以双指针维护当前点和决策点。

\(\color{blueviolet}{CF10E}\)

不得不说这题太神秘了。

考虑贪心什么时候是错误的。假设贪心会选择 \(a_i\),然后选择 \(a_j\),存在一种更优情况一定是选择两者之间的某一个值进行拼凑,然后枚举 \(i, j\) 尽量小的构造即可。

证明过程很神秘,略了。

\(\color{blueviolet}{CF543C}\)

状压是显著的,设 \(f_i\) 表示达到状态 \(i\) 时的最小花费,其中状态表示每一个字符串是否存在一位不同。

考虑对于一个 \(f_i\) 进行向下转移,找到第一个不合法字符串 \(now\),有两种转移方式,第一种是改这个字符串使得其合法,第二种是改一群某位相同的字符串,使得这一群字符串合法。

第一种转移是显然的,第二种考虑预处理一个 \(g_{i, j}\) 表示将第 \(j\) 位与第 \(i\) 个字符串相等的一群字符串都改合法的方案,显然是不改花费最大的那个,预处理是简单的。

\(\color{blueviolet}{CF555B}\)

题意转化为给定一些点和区间,一个点可以覆盖至多一个它所在的区间,每个区间至少被一个点覆盖,问是否有覆盖方案。

把区间按照右端点排序,然后在 set 里二分合法最靠左点来覆盖区间,找不到就是无解。

\(\color{blueviolet}{CF442C}\)

首先有一个显著的结论,如果一个数两边都比它大,那么删去这个数是最优的,于是可以用单调栈维护第一步。

删完之后得到一个单峰序列,最优方案经过手玩可以得出是取最大次大外的所有的贡献,这两个数永远取不到。

\(\color{blueviolet}{CF833C}\)

没法前缀作差,考虑其他做法。

发现了不同的数的个数一共不多,所以可以枚举所有数并进行判断是否在区间内。

\(\color{blueviolet}{CF678F}\)

没有删除操作就是李超线段树板子,套一个线段树分治即可。

\(\color{blueviolet}{CF601C}\)

状态是好想的,\(f_{i, j}\) 表示前 \(i\) 场比赛分数和为 \(j\) 的期望人数。

有转移 \(f_{i,j} = \dfrac{\sum\limits_{k=1}^m{f_{i-1,j-k}\ (k \ne c_i)}}{m-1}\)

\(\color{royalblue}{CF1343E}\)

简单题,首先考虑不能直接贪心的原因,两段最短路可能有重叠部分,重叠部分有且只有可能是由 \(B\) 出发的一段路径。

考虑枚举中转点 \(D\),使得 \(2dis_{D, B} + dis_{D, A} + dis{D, C}\) 最小,发现做三遍 BFS 即可。

\(\color{blueviolet}{CF639D}\)

有点质量的题。

\(v\) 进行排序是显然的。

首先只考虑加一的操作,枚举最终达到的值 \(v_i\),对于排好序的 \(v\) 序列,越靠后的数字花费越少,所以最终一定选择的是 \(v_{i - k +1}\)\(v_i\)。如果只是这样我们可以直接拿前缀和算,但是其不足以扩展出此题正解,我们考虑劣化整个计算过程。

依然固定最终值 \(v_i\),考虑用队列维护选择的元素,在维护过程中加入一个元素,如果目前已经有 \(k\) 个元素且这个元素的花费比最大花费要小,那么我们此时去掉最大花费加入此元素一定更优。因为上文提到的花费单调性,所以此时队首一定是最大花费元素,直接弹出队首即可。

当存在加五操作时,花费单调性将不对整个序列存在(比如上一个元素可以通过加五到达目标值,而当前元素只能通过加一操作达到,此时当前花费可能更大。),因此不能直接用队列维护。考虑到将所有余数相同的数拿出来之后仍然具有单调性,所以可以按照余数分类(对 \(5\) 取模),对于每个余数做一个队列,所有队列中元素总个数不超过 \(k\),每次尝试从所有队首弹出最大的进行决策。

再考虑加五操作的另一种影响,目标值可能不一定是 \(v_i\),也可能是 \(v_i + val \quad (0 \le val < 5)\),所以都枚举一遍进行计算即可,带有五倍常数,去掉重复枚举可以减小常数。

注意如果 \(b > 5c\)\(b \leftarrow 5c\)

\(2023.12.4-2023.12.10\)

\(\color{blueviolet}{CF827C}\)

好题。

\(1 \le |e| \le 10,|\sum| = 4\),考虑从这几点下手。

首先每个字符可以分开考虑,然后对于每个长度,每个匹配的字符位置开一个树状数组。

本质上是判断同余位置的字符相等个数,也就是对于每种字符,每个模数,每个余数开一个树状数组,总计 \(400\) 个,空间允许。

\(\color{blueviolet}{CF842E}\)

简单题。

先最小生成树一下,分别考虑树边与非树边的答案,设一个边为 \((u, v, w)\)

非树边的答案是平凡的,即树上 \(u, v\) 路径上边权取最大值再减一。

树边的答案考虑增大到某一时刻一定会被某条较小的非树边取代,所以考虑非树边从大到小路径覆盖即可(取最小值减一)。

特别地,某条边没被覆盖到那也就是必选边,答案为 \(-1\)

\(\color{blueviolet}{CF832D}\)

细节还是有点水平的。

对于一个询问枚举三种情况是显著的,设 \(x, u, v\) 三点表示重复点与令两点。

对于 \(u, v\)\(x\) 子树内或不在的情况进行分类处理。特别地,两者都不在的时候考虑 \(LCA(x, u)\)\(LCA(x, v)\) 是否相等,剩下的是平凡的。

\(\color{blueviolet}{CF842E}\)

神仙题。

主要用到一个性质,多条直径一定至少交于一点或一条边。

考虑一个交点,将直径分为两段,这两段长度可能一样可能不一样(与直径长度奇偶性相关),只需考虑不一样的情况。

设两段端点集合为 \(s1, s2\),每次加入一个点 \(i\),跟两集合内任意一点求距离设为 \(d_1, d_2\)。若 \(d_1, d_2\) 其中一个能更新直径,以 \(d_1\) 为例,那么 \(s_2\) 中的点可能失效,考虑其不失效的充要条件为 \(dis(x, i) = d_1\) 其中 \(x \in s_2\),现在这样的点符合 \(s_1\) 的条件,加入 \(s_1\) 即可,然后清空 \(s_2\)

每次模拟上述过程,输出两集合大小之和即可。

\(\color{blueviolet}{CF838D}\)

更加神仙的题!

考虑所有情况中合法的概率,假设每个人随机指定位置随机走,将 \(1 \sim n + 1\) 连成环,其中 \(n + 1\) 是增加的位置,此位置是起点,若绕一圈并占据了此节点说明此方案不合法。

结论是所有位置等价,所以占据 \(n + 1\) 的概率为 \(\frac{m}{n + 1}\),合法概率即 \(\frac{n + 1 - m}{n + 1}\),乘以总方案数 \(2 ^ m (n + 1) ^ m\) 即答案。

结论不知道怎么证明,但感性理解挺正确的。

\(\color{black}{CF1466I}\)

考虑用队列维护最优前缀,每次加入一个数并尝试扩展一位,不优就舍掉。

下一步从队尾向队首计算,不优就弹掉整个队列后缀。

第一步计算是冗余的,不必判断是否相等,因为在第二步会处理劣解。

用 string 以及内置函数可以大大减小实现难度。

\(\color{blueviolet}{CF1753D}\)

很好的题,注意到一个结论,一个块最多只会被移动一格(保证移动后一定跟原来位置有交)。

于是可以看做在途中移动一个方格,设 \(f_i\) 表示将某个空位移动到格子 \(i\) 的最小代价,答案即两个相邻位置的代价和。

其实看似这个 DP 会有一些重复和疏漏,其实正确性是可以证明的,非常巧妙,可惜题解里没人提到这些。(哈哈我也不写!)

\(\color{blueviolet}{CF1765C}\)

我会找时间补充这道题的详细题解。

\(\color{blueviolet}{CF487D}\)

考虑将 \(n\) 分块维护,设 \(to_{x, y}\) 表示从 \((x, y)\) 出发走到的第一个块外位置,特别的,如果从此点出发会停止在此块内那么就记为答案。

修改的时候就整块重构,这里加个剪枝从修改的位置开始,因为只会向下影响,跑得飞快。

询问是简单的,一直跳坐标直到不能跳为止。

\(\color{blueviolet}{CF521D}\)

最开始看错题了以为是水题,漏掉了至多选 \(m\) 个的条件。

首先不难想到一些结论:

  1. 若选定了一些操作,那么操作顺序一定是赋值、加法、乘法。
  2. 对于一个数来说,赋值至多赋一次。
  3. 对于一个数来说,一定优先选择大的加法。
  4. 乘法的贡献与乘的位置无关,只与乘的数有关,所以一定是选最大的一些乘法。

不难想到如果只有乘法和加法,问题也是简单的,因为加法的选择一定从高到低,这样可以计算出选择每个加法的实际贡献,转成乘以一个实数。

然后想到赋值只有一次,对于数字的影响也可以看做加法,于是这题就做完了。

\(\color{blueviolet}{CF468B}\)

类似二分图的东西,逻辑是有趣的。

首先考虑数字 \(x\),若 \(a - x\) 已经给出了,那么两者一定同集合。证明是简单的,考虑如果 \(x\) 在集合 \(A\),那么 \(a - x\) 一定在集合 \(A\);如果 \(x\) 不在 \(A\) 内,那么 \(a - x\) 也不能在 \(A\),只能在 \(B\) 内。对于 \(b - x\) 同理,所以可以这样合并 \(x, a - x, b - x\)

考虑数字 \(x\),若 \(a - x\) 未给出,那么 \(x\) 只能在 \(B\) 内,直接塞进去即可。

这实际上是一个类似二分图的东西,可以用并查集瞎维护,建两个虚点表示集合 \(A, B\),按照上述方式进行合并,最后判断两个虚点是否在一块,如果在一块则无解。

\(\color{blueviolet}{CF452F}\)(\(\color{blueviolet}{P2757}\) 双倍经验)

非常神秘的题目,采用非常神秘的做法,非正解。

智慧的鹿目圆如是说道。

\(\color{blueviolet}{CF1375E}\)

记录 \(p_i\) 表示当前 \(a_i\) 最初在什么位置,每次对数组 \(a\) 进行冒泡排序,排序每次交换记录一下 \(p\) 作为答案,并更新 \(p\),需要倒序输出。

正确性非常神秘,将操作序列映射到了原序列,又由于冒泡排序每次必定恰好消灭一个逆序对,所以保证了每次操作都是一个逆序对。

实际上 \(p\) 数组经过一系列排序后相当于原序列的逆排列,而这种做法已经被验证是正确的了,所以此做法也应当正确。

\(\color{blueviolet}{CF825F}\)

考虑 DP,分段 DP 是显著的,考虑设 \(f_i\) 表示以 \(i\) 结尾的前缀的压缩最小长度。

转移时考虑枚举断点进行转移。

不难得出一个结论:对于一个串来说肯定找到最小循环节压缩是最优的,证明是简单的。

于是问题转化为如何 \(O(1)\) 找一个子串的最小循环节,这时候用到一个结论,对于一个长度为 \(n\) 的串,其最短循环节为 \(n - nex_n\)(其中 \(nex_i\) 是 KMP 中求的 border,并且当且仅当此值能整除串长时成立),于是可以 \(O(n^2)\) 预处理每个后缀的 border,剩下的都是平凡的。

\(\color{blueviolet}{CF883B}\)

比较平凡的题目。

先正向反向求出每个节点的权值上下界,然后贪心求解方案即可。

\(\color{blueviolet}{CF297C}\)

考虑排序后分三段构造,设 $t = \left \lceil \frac{n}{3} \right \rceil $。

第一段 \(1 \le i \le t\)

\(a_i = i - 1, b_i = s_i - a_i\)

第二段 \(t + 1 \le i \le n - t\)

\(b_i = i - 1, a_i = s_i - b_i\)

第三段 \(n - t + 1 \le i \le n\)

\(b_i = n - i, a_i = s_i - b_i\)

\(\color{blueviolet}{CF626F}\)

神秘的 DP 题。

首先不难想到的是把 \(a\) 排序,分组时只需要考虑最小值,因为每次加入一个数一定是最大值。

设 DP 式 \(f_{i, j, k}\) 表示处理到第 \(i\) 个数,目前有 \(j\)未封闭的组,总不和谐度之和为 \(k\) 的方案数。

考虑第 \(i\) 个数的放置情况:

  1. 加入某个组,保持此组仍为开放。

  2. 加入某个组,封闭此组。

  3. 新建某个组,开放此组。

  4. 新建一个组,封闭此组。

对于新建一个组需要转移负贡献,也就是 \(k \leftarrow k - a_i\),封闭一个组需要加入当前贡献 \(k \leftarrow k + a_i\)

转移是简单的,但此方法复杂度较高,而且第三维会出现负数,比较难处理。

尝试给出一种较为好理解优化的方式。把每个组想象成一条正在延伸的线段(若已封闭那么这条线段不会延伸),左端点是组内最小值,右端点是最大值,考虑加入一个 \(a_i\),那么未封闭的所有组最大值至少为 \(a_{i + 1}\),也就是有 \(k \leftarrow k +j \times (a_{i + 1} - a_i)\),相当于所有未封闭线段右端点右移一段距离。

考虑把贡献都变成差分的形式,第三维没了负数,并且值域变小,转移随便写写即可,时间复杂度 \(O(n ^ 2 \max\{k, \max\{a_i\}\})\)

\(\color{blueviolet}{CF1845E}\)

状态是神秘的,设 \(f_{i, j, k}\) 表示前 \(i\) 个位置放了 \(j\)\(1\),最少可以用 \(i\) 步移动到此状态的状态总数。

第三维是巨大的,发现其上限是 \(O(\sqrt n)\) 的,转移的时候剪枝一下即可。

\(\color{blueviolet}{CF708B}\)

\(0/1\) 的数量都可以求出,然后化式子判断一波即可,已知有解之后贪心放即可。

\(\color{blueviolet}{CF1842H}\)

非常好题目啊。

考虑令 \(x_i \leftarrow x_i +0.5\),限制变为与 \(0\) 的大小关系,注意到这个式子是否成立只需要考虑绝对值较大的数的正负,考虑从小到大加入 \(x_i\),枚举状态,再枚举加入哪一个求出合法方案,除以总方案即答案。

\(\color{royalblue}{CF1537E2}\)

题意可以简化,对于一个前缀复制粘贴到长度为 \(k\)(截断),求所有前缀中这样操作后串字典序最小的。

记录一个最优前缀,枚举当前前缀,比较两者当前位(\(s_i, s_{i \ mod p}\)\(p\) 为记录的最优前缀),可以达到线性复杂度。

\(\color{royalblue}{CF1472G}\)

简单题。

我们称能走多次的为正边,只能走一次的为反边,很显然你要么不动,要么走一些正边最后走一次反边。

先 BFS 处理每一个点的层级,然后 DFS 更新即可,通过正边更新 \(f_{now} \leftarrow \min\{f_{now}, f_{to}\}\),反边则 \(f_{now} \leftarrow \min\{f_{now}, lev_{to}\}\)

\(\color{black}{CF936D}\)

直线上行走能开炮就开炮等价于可以攒能量,拐弯时需要与 \(t\)\(\min\),把每个位置以及下一个位置离散进行 DP 即可,记录转移来源,细节有亿些多。

\(\color{blueviolet}{P2824}\)

尝试二分最后答案,对于所有数字若大于等于 \(mid\) 则设为 \(1\),否则为 \(0\),只有 \(0, 1\) 时可以用线段树维护在 \(O(\log n)\) 时间内进行一次排序。最后发现询问的位置是 \(1\) 则合法。

\(\color{blueviolet}{P5025}\)

采用一种神秘的 \(O(n)\),考虑像省选 D1T1 一样处理,从每一个向左扩展,再向右扩展,进行剪枝之后是均摊正确的。

\(\color{royalblue}{CF1493D}\)

首先有一种显然的做法,即开质数数量棵动态开点线段树,发现可以用 set 替代,就简单地做完了。

\(\color{royalblue}{CF351B}\)

发现答案是逆序对数二倍,奇数需要减一,证明是简单的。

\(\color{royalblue}{CF16E}\)

状压表示鱼的存活状态,考虑倒序转移即可,注意鱼与鱼相遇的概率相等。

\(\color{royalblue}{AT\_abc286\_g}\)

并查集缩点然后判是否存在欧拉通路。

\(\color{royalblue}{AT\_abc286\_f}\)

本质上是一些环,考虑构造一些环长互质的环然后 CRT 即可,逆元甚至可以暴力求。

\(2023.12.11-2023.12.17\)

\(\color{blueviolet}{CF494C}\)

区间不会交错,使得可以根据区间包含关系建出一颗森林,我们添加一组 \(l = 1, r = n, p = 0\) 的修改,可以保证是一棵树,考虑 DP。

\(f_{i, j}\) 表示 \(i\) 子树内,最大值为 \(j\) 的概率,但这样并不好转移,考虑改变状态,有 \(f_{i, j}\) 表示 \(i\) 子树内,最大值不超过 \(j\) 的概率,这样转移是简单的,考虑当前节点是否成功修改即可。

第二维状态仍然很大,但其中有很多无用状态,考虑剪枝。对于一个节点 \(i\),设操作前最大值为 \(mxv_i\),那么操作后最大值的范围是 \([mxv_i, mxv_i + q]\),所以再次改变状态,设 \(f_{i, j}\) 表示第 \(i\) 子树内,最大值不超过 \(mxv_i + j\) 的概率,转移的时候作差削除差异即可。

\(\color{blueviolet}{P9871}\)

线段树优化 DP 是显著的,离散一下即可。

\(\color{blueviolet}{CF786C}\)

答案是一段一段连续的,对于较小的数直接暴力做,对于大的数考虑每次二分一个连续答案段即可。

\(\color{blueviolet}{P9870}\)

非常好思维题。

钦定 \(f_i < g_i\),可以转化为网格行走,节点 \((i, j)\) 可以走的条件为 \(f_i < g_j\),每次找 \(f\) 最小值与 \(g\) 最大值的一列和一行进行递归处理即可。

\(\color{blueviolet}{P7735}\)

考虑打时间戳,每次操作对于路径上的点改变颜色为当前操作编号。问题转化为求某路径上颜色相同相邻两点对数,树剖加线段树即可。

\(\color{blueviolet}{P4008}\)

平衡树裸题,细节一堆,还算好写。

\(\color{blueviolet}{CF1334F}\)

没看懂 \(O(n \log n)\) 写法,写的 \(O(n)\) 的。

为了方便处理边界,在 \(a, b\) 两序列前后分别加上 \(0, n + 1\),下标从 \(0\) 开始。

考虑给 \(a\) 重新赋值:

  • \(a_i = b_j\),则使 \(a_i \leftarrow 2j\)
  • \(b_j < a_i < b_{j + 1}\),则使 \(a_i \leftarrow 2j + 1\)

题意转化为保留一个 \(0, 2, 4, \ldots 2m\) 的序列,在第一个 \(2i\) 出现之前不能出现 \(2i - 1\),简单思考后可以发现此限制与原限制等价,然后就可以考虑 DP 了。

\(f_i\) 表示到 \(i\) 为止,只考虑权值不超过 \(2j\) 的贡献的最小花费,其中需要保证 \(a_i = 2j\)

首先考虑强制 \(a_i\) 作为第一个 \(2j\) 出现,有:

\(f_i=\{f_x+\sum_{k=x+1}^{i-1}[p_k<0]p_k\}+\sum_{k=0}^{i-1}[a_k=2j\lor a_k=2j-1][p_k>0]p_k\)

其中 \(a_x = 2j - 2\),我们只需要从最近的 \(2j - 2\) 转移过来即可。

对于不考虑取第一个的话有转移:

\(f_i=\{f_x+\sum_{k=x+1}^{i} [p_k<0]p_k\}\)

代码是简单的,随便写写即可。

\(\color{blueviolet}{CF962F}\)

考虑在 DFS 生成树上乱搞。

首先考虑非树边(即返祖边),当它覆盖到的所有树边都只被覆盖一次(只被它覆盖),那么此非树边合法。

对于树边,当它只被非树边覆盖一次,并且此非树边合法,此树边合法。

考虑树上差分处理覆盖次数,然后找合法非树边,暴力判断是否合法,若合法再将其覆盖到的树边标记为合法即可。

\(\color{royalblue}{AT\_abc287\_f}\)

神秘的树背包,稍微有点细节的。

\(f_{i, 0/1, j}\) 表示在 \(i\) 子树内,选不选自己,已选 \(j\) 个连通块的方案数。

\(\color{royalblue}{AT\_abc287\_g}\)

没啥水平题,建个动态开点权值线段树,维护一下和与数字个数,然后线段树上二分即可。

\(\color{blueviolet}{AT\_abc287\_h}\)

没啥水平题,Floyd 枚举中转点然后判连通,用 bitset 优化即可。

\(\color{blueviolet}{CF1044D}\)

垃圾翻译,题目里没提到的要求是若此条信息与前些信息矛盾则忽略此信息。

带权并查集维护异或和即可。

\(\color{royalblue}{CF1271E}\)

对于答案 \(x\) 的出现次数是单调的,考虑二分 \(x\),并求其出现次数判断是否合法。出现次数只要考虑在完全二叉树上的贡献即可,一层一层算,复杂度是 \(O(\log n)\) 的。

\(\color{blueviolet}{CF1097D}\)

\(f_{k, i}\) 表示对 \(i\) 操作 \(k\) 次后的期望值,考虑列出其所有因数进行求解式子是显著的。

发现这个东西是积性的,即 \(f_{k, a /times b} = f_{k, a} \times f_{k, b} \quad(\gcd(a, b) = 1)\),推导是简单的。

然后考虑对于每个质因子做一遍 DP,记忆化下来可过。

\(\color{blueviolet}{P4180}\)

严格次小生成树板题,倍增维护最大次大值即可。

\(\color{blueviolet}{CF847J}\)

考虑网络流建模,二分最大送礼物数量作为每个人的总容量,对于每一个限制(一条边),连两个人到其的边,并连向汇点。

能流满即存在合法方案,输出方案考虑哪条边流满了即可。

\(\color{royalblue}{P2619}\)(\(\color{blueviolet}{SP11579}\) 双倍经验)

wqs 二分练习题。

考虑直接求最小生成树,我无法控制加入了多少白边,考虑直接调整白边本身权重,如果我希望多要一些白边那么就让所有白边的权重都减少一些,否则增加,像这样子二分即可。

考虑正确性,首先存在这样一种情况,权重调整值为 \(mid\) 的时候白边小于 \(\mathrm{need}\),为 \(mid + 1\) 的时候白边大于 \(\mathrm{need}\)。存在这样情况的条件一定是存在白边和黑边边权相同了,否则决策不会改变,然后保证优先选白边可以保证一定存在临界点与正确答案相同。

本质上相当于我们二分一条直线的斜率去切这个答案的凸包。

\(\color{blueviolet}{CF739E}\)

暴力是简单的,不难想出 \(f_{i, j, k}\) 表示前 \(i\) 个宝可梦用了 \(j\) 个宝贝球,\(k\) 个超级球所能得到的最大期望,复杂度是 \(O(n^3)\) 的,可以考虑优化掉后一维或两维,换成 wqs 二分即可。

\(\color{royalblue}{P3620}\)(\(\color{blueviolet}{SP1553}\) \(\color{blueviolet}{CF958E2}\) 多倍经验)

\(f_{i, 0/1}\) 表示以 \(i\) 结尾,\(i\) 是否已经被选的最小代价。

只这样 DP 无法控制选择了多少对,用 wqs 二分即可。

\(\color{blueviolet}{CF321E}\)

二维 DP 是显著的,考虑套 wqs 二分,转移用决策单调性队列二分即可。

\(\color{blueviolet}{CF55D}\)(\(\color{blueviolet}{SP8177}\) 双倍经验)

数位 DP,主要难点是想到按模数分类进行 DP。

\(\color{blueviolet}{CF830D}\)

没咋做明白的 DP,考虑以每个点作为根合并子树内链进行计数即可。

\(2023.12.18-2023.12.24\)

\(\color{blueviolet}{CF121E}\)

看题解之后选择了一种较为优异的写法。

树状数组维护每个位置是否是合法数字,区间修改直接暴力修改,发现此处的值贡献有变再用树状数组进行修改,枚举的复杂度是巨大的,但考虑到每个数递增,并且合法数字数量不多,所以修改次数是少量的,总复杂度大概 \(10^9\) 出头,常数很小,跑得飞快。

\(\color{blueviolet}{CF429C}\)

按子树大小从大到小枚举合法父亲进行搜索,复杂度是阶乘级别,无法接受。

发现子树大小为 \(1\) 的节点父亲是谁都无所谓,所以不用枚举,并且根据题目中“非叶子节点子节点个数至少为 \(2\)”这条性质可以得到叶子节点个数超过一半,复杂度降为 \(\left\lfloor \frac{n}{2} \right\rfloor !\),可以接受。

\(\color{blueviolet}{CF1394D}\)

首先转化题意,相当于对于每个边选定其方向,然后合并合法路径减小总代价。

考虑没有 \(b_i = b_j \quad (i \not= j)\) 情况,也就是说相邻点对的大小关系是固定的。此时对于任意边 \((u, v) \quad (b_u < b_v)\),都钦定方向 \(u \to v\) 是最优的。(或者都钦定为 \(v \to u\),这两种方式等价,此题解中采用 \(u \to v\)。)此时一个点 \(u\) 贡献的代价 \(val_u\)\(\max \{ d0_i, d1_i \} \times a_u\),其中 \(d0_u, d1_u\) 分别表示其入度和出度。总代价即所有点代价之和。

重新考虑原问题,我们设 \(f_{i, 0/1}\) 表示节点 \(i\) 子树内,在 \((i, fa_i)\) 这条边被钦定为向上/向下的最小代价。假设现在正在处理节点 \(u\),对于 \(b_v \not= b_u\) 的子节点 \(u\) 的贡献是固定的,我们只需要考虑 \(b_v = b_u\) 的贡献。我们先钦定这些边都是向上的,即 \(v \to u\),接下来的问题就是从这些子节点中挑一些将其钦定为 \(u \to v\),使得总代价最小。调整一个点对于 \(a_u\) 的数量贡献是固定的,于是我们贪心地优先调整 \(f_{u, 1} - f_{u, v}\) 较小的点。

考虑记录所有的 \(b_u = b_v\)\(v\),将其按照 \(f_{u, 1} - f_{u, v}\) 从小到大排序,每次调整贡献并尝试更新。

特别地,考虑 \(f_{u, 0}\) 使 \(u\) 的出度加一,\(f_{u, 1}\) 使 \(u\) 的入度加一,这考虑的是边 \((u, fa_u)\) 被钦定的方向,如果 \(b_u \not= b_v\),那么 \(0/1\) 状态中只有一个会被使用。

\(T_u\) 表示 \(u\) 的子树,\(T0_u\) 表示被钦定为 \(v \to u\) 的点 \(v\) 的集合,\(T1_u\) 表示被钦定为 \(u \to v\) 的点 \(v\) 的集合(向上/向下连边的两个子节点集合),于是有以下形式化的转移:

\[f_{u, 0} = \min \left\{ \sum \limits_{v \in T0_u} f_{v, 0} + \sum \limits_{v \in T1_u} f_{v, 1} + \max \left\{|T0_u|, |T1_u| + \left[u \not= 1\right] \right\}\times a_u \right\} \]

\[f_{u, 1} = \min \left\{ \sum \limits_{v \in T0_u} f_{v, 0} + \sum \limits_{v \in T1_u} f_{v, 1} + \max \left\{|T0_u| + \left[u \not= 1\right], |T1_u|\right\}\times a_u \right\} \]

以上式子中的 \(\left[u \not= 1\right]\) 表示以 \(1\) 为根进行 DP 时,其没有父节点,也就不存在与父节点连边的那个度数。

\(\color{blueviolet}{CF1101F}\)

用到了一个奇妙 Trick。

对于每辆车可以考虑二分油箱容量,进行贪心验证,每次不能走了就加油,最后判断加油次数是否小于限制即可。

如果暴力二分是 \(nm\log V\) 的,不太能接受,发现其中有一些答案是无用的,比如前 \(i - 1\) 辆卡车的答案为 \(ans\),第 \(i\) 辆卡车在 \(ans\) 的情况下合法,我们就无需计算 \(i\) 的答案。

这样有了一些小剪枝,但发现当答案单调上升的时候复杂度仍然会卡到上界,考虑随机化优化一下。

有如下结论:对于长度为 \(n\) 的随机序列,前缀最大值的个数为 \(O(\log n)\)

证明是简单的。对于一个排名\(x\) 的数字,需要保证所有比它大的数字都要出现在其后面,则其为一个前缀最大值。我们将排名依次为 \(x, x + 1, \dots , n\) 的数字作为一个子序列拿出来,\(x\) 为前缀最大值的概率等价为 \(x\) 在这个子序列中是第一个数的概率,所以有其概率为 \(\frac{1}{n - x + 1}\)。期望个数即 \(\frac{1}{1} + \frac{1}{2} + \dots + \frac{1}{n}\),积分后可以得到是 \(O(\log n)\) 的。

所以我们对于每辆卡车随机赋权值,并按照权值排序,这样得到的前缀答案最大值期望个数为 \(O(\log m)\),所以总期望复杂度为 \(O(n \log m \log V + m\log V)\),可以接受。

\(\color{blueviolet}{CF671C}\)

优美的题,感觉很仙。

一般这种题可以先考虑枚举左端点,然后看所有右端点的整体贡献,但这道题要求 \(\gcd\) 很不友好,无法这么处理。稍微转换一下思路,枚举答案,求每种答案的方案数,根据差分思想可以考虑求答案 \(\le i\) 的总方案数(下文称为 \(val_i\)),这样对于每个 \(i\) 求完之后可以差分得到某个值的答案,这样最终答案的计算是简单的。

\(i\) 为当前枚举的答案上界,我们尝试求出 \(f(l, r) \le i\) 的合法 \((l, r)\) 数量。首先观察到当 \(i\) 为极大值的时候,所有区间都是符合条件的,因此我们考虑从大到小枚举 \(i\) 每次修改贡献的变化量。

固定现在枚举到的 \(i\),设 \(nex_j\) 为对于第 \(j\) 个数,在保证 \(f(j, r) \le i\) 的条件下的最小的 \(r\),若不存在这样的 \(r\)\(nex_j = n + 1\)。于是有:

\[val_i = \sum \limits_{1 \le j \le n} n - nex_j + 1 = n(n + 1) - \sum \limits_{1 \le j \le n} nex_j \]

所以只需要考虑维护 \(nex_j\) 的和即可,现在考虑当 \(i\) 变为 \(i - 1\) 我们修改什么。显然地,对于所有答案等于 \(i\) 的区间我们需要舍去,而只有是 \(i\) 的倍数的数才能造成贡献。在某个所选区间外(即没有删除的数中),\(i\) 的倍数至多出现一次时,此区间才可以合法,换句话说,我们需要将所有区间外存在多个 \(i\) 的倍数的区间扩展,考虑分类讨论进行扩展。

\(p_1, p_2, \dots, p_{k - 1}, p_k\) 表示 \(i\) 的倍数的出现位置(\(p_t < p_{t + 1} \quad (1 \le t < n)\)),分以下几种进行讨论:

  • \(1 \le j \le p_1\):此时区间左侧没有 \(i\) 的倍数,所以我们可以让区间右侧出现至多一个 \(i\) 的倍数,有 \(nex_j \leftarrow \max\{nex_j, p_{k - 1}\}\)

  • \(p_1 < j \le p_2\):此时区间左侧有一个 \(i\) 的倍数,所以我们必须让区间包括右侧所有 \(i\) 的倍数,有 \(nex_j \leftarrow \max\{nex_j, p_k\}\)

  • \(p_2 < j\):此时我们不论如何修改 \(nex_j\) 都没有合法的值,因为区间左侧永远有至少两个 \(i\) 的倍数,所以 \(nex_j \leftarrow n + 1\)

我们知道维护逻辑后考虑维护方式,这个东西是一个区间对某个数取 \(\max\),全局询问和的东西。

单纯的维护是较为困难的,我们需要注意到 \(nex_j\)\(i\) 固定时的取值是单调不降的,也就是说区间 \([l, r]\) 对某数 \(v\)\(\max\) 等价于将某段区间 \([l, x]\) 全都赋值为 \(v\)(也可能完全不赋值),这个东西是可以用线段树上二分解决的。所以考虑将 \(nex_j\) 扔到线段树上维护,线段树上二分时需要注意边界以及返回条件。

目前为止还没有提到 \(p\) 的求法,我们发现只有 \(p_1, p_2, p_{k - 1}, p_k\) 是有用的,所以对于每个数字只需要求出其倍数的前两次出现和后两次出现即可。维护方式是简单的,首先预处理每个数的约数,复杂度是 \(n\ln n\) 的,然后对于每个输入的 \(a_i\) 都枚举其因数,用 \(i\) 去更新维护的 \(p\),详见代码。这里因为 \(a_i\) 互不相同所以复杂度是调和级数的,如果 \(a_i\) 都拉满并且相同,那预处理复杂度上界应该就是 \(n\sqrt V\) 了。

最后注意所有 \(nex_j\) 初值都有 \(nex_j = j\)

\(\color{blueviolet}{CF1795F}\)

二分这个操作次数,然后处理出来每个人需要走多少步,贪心地向下走,找向下深度最大的能走的位置,如果向下不够就尝试把贡献转移到父节点,前提是父节点是合法点,DFS 判断即可。

\(\color{blueviolet}{CF398B}\)

\(f_{i, j}\) 表示剩下 \(i\)\(j\) 列没有颜色,达到每行每列都被染色的状态的期望步数。

这一次涂色,\(\dfrac{i}{n}\times \dfrac{j}{n}\) 的概率涂的是剩下的 \(i\)\(j\) 列相交区域的格子,还需要期望 \(f(i-1,j-1)\) 次;

这一次涂色,\(\dfrac{i}{n}\times \dfrac{n-j}{n}\) 的概率涂的是剩下的 \(i\) 行,但不是剩下的 \(j\) 列中的格子,还需要期望 \(f(i-1,j)\) 次;

这一次涂色,\(\dfrac{n-i}{n}\times \dfrac{j}{n}\) 的概率涂的是剩下的 \(i\) 行,但不是剩下的 \(j\) 列中的格子,还需要期望 \(f(i,j-1)\) 次;

这一次涂色,\(\dfrac{n-i}{n}\times \dfrac{n-j}{n}\) 的概率涂的既不是剩下的 \(i\) 行,也不是剩下的 \(j\) 列中的格子,还需要期望 \(f(i,j)\) 次。

所以有:

\[\begin{aligned}f(i,j)=1+\frac{ij}{n^2}f(i-1,j-1)+\frac{i(n-j)}{n^2}f(i-1,j)+\frac{(n-i)j}{n^2}f(i,j-1)+\frac{(n-i)(n-j)}{n^2}f(i,j)\end{aligned} \]

\[\begin{aligned}f(i,j)=\frac{n^2+ijf(i-1,j-1)+i(n-j)f(i-1,j)+(n-i)jf(i,j-1)}{in+jn-ij}\end{aligned} \]

\(i, j\)\(0\) 时有边界条件,是简单的。

\(\color{blueviolet}{CF1442D}\)

有这么一个性质,至多只有一个序列没有选满,否则一定可以通过调整得到更优解。

先考虑暴力 DP,用背包即可,现在可以枚举零碎序列,然后将其他的每个序列做 \(0/1\) 背包,枚举到的内部做一下背包即可。

这样复杂度升天,考虑用分治优化,每次处理除了当前 \([l, r]\) 以外的背包,递归下去即可,时间复杂度可以接受。

\(\color{blueviolet}{CF414C}\)

考虑每次修改会影响的只有每段的内部逆序对,可以用 CDQ 预先处理出来每一层的两种逆序对数,根据询问累加并交换即可。

\(\color{blueviolet}{CF840D}\)

主席树板子,两树联查,树上二分即可。

\(\color{blueviolet}{CF771C}\)

非常好题目啊。

首先考虑题目让你求的到底是个什么东西,不难看出 \(f(u, v) = \left\lceil\frac{dis(u, v)}{k}\right\rceil = \frac{dis(u, v) + (k - dis(u, v) \mod k)}{k}\),然后这个东西求和可以直接求分子的和然后最后除以 \(k\)

分子一共有两部分,第一部分是所有路径的长度和,可以用点分治直接求,但第二部分貌似看起来有点困难。考虑到 \(k\) 比较小,所以可以尝试按余数分类,设 \(ans_i\)\(dis(u, v) \equiv i \pmod{k}\),的路径条数,那么第二部分即 \(\sum \limits_{0 \le i < k} ans_i(k - i)\),也就是说第二部分只需要求出路径长度模 \(k\) 为各个余数的路径数量即可,这个东西也可以用点分治维护,每次更新记一个桶,然后用乘法原理计数即可。

\(\color{blueviolet}{CF578D}\)

考虑转化题意,将原字符串去掉一个字符,在任意一个位置添加一个字符,问能通过这样得到多少个不同的字符串。

考虑直接计数所有情况,并去掉重复贡献。枚举原字符串去掉的字符(相同连续段只枚举一次),添加任意一个字符的方案为 \(nm\),其中 \(m\) 是字符集大小。

第一种重复情况,假设去掉一个字符后串中有一个字符 a 那么在其左右两侧添加一个字符 a 的效果相同,这样的重复总共有 \(n - 1\) 种,所以答案减去 \(n - 1\)

第二种重复情况,假设原字符串的一个子串 ab,去掉 ab 后添加 a 的效果,与去掉 ba 前添加 b 效果相同。这种重复存在于所有不同的相邻字符之间,考虑对于枚举的每个不是字符串首位的字符答案都减去 \(2\)

第三种重复情况,对于一种 \(\{a, str, b\}\) 的情况(\(a, b\) 为字符,\(str\) 为一段字符串),我们经过变换可以得到 \(\{b, a, str\}, \{str, b, a\}\) 两种排列,当 \(str\) 是由 \(b, a\) 交替组成的循环节为 \(2\) 的字符串时会出现重复。所以对于 \(\{a, b, \dots, a, b\}\) 的这种极长连续段考虑减去其所有子串。对于这个有巧妙的方式解决,设 \(cnt\) 为连续的 \(s_{i - 1} = s_{i + 1}\) 个数,其中 \(i\) 是正在枚举的位置,不能是起始或终止位置,每次将答案减去 \(cnt\) 即可。

\(\color{blueviolet}{CF786B}\)

线段树优化建图板子,自叶子向上、自根向下两棵线段树即可。

\(\color{blueviolet}{CF581F}\)

树背包板子,设 \(f_{i, j, 0/1}\) 表示节点 \(i\) 子树内有 \(j\) 个叶子为黑色,自己的颜色为 \(0/1\) 的最小代价,转移是简单的。

\(\color{blueviolet}{P3648}\)

把贡献式子写出来拆开后发现决策顺序与答案无关,所以变成了经典的分段 DP,决策单调性证出来后斜率优化即可。

\(\color{blueviolet}{P4360}\)

当第二个锯木厂 \(i\) 递增时,最优的第一个锯木厂 \(j\) 的位置单调不降,决策单调性分治即可。

\(\color{blueviolet}{CF1572C}\)

去个重先,连续段都缩到一起。

区间的状态是明显的,设 \(f_{i, j}\) 表示区间 \([i, j]\) 内颜色都变成 \(c_j\) 的最小代价。\(n^3\) DP 是显著的,每次枚举中转点 \(k\),拼凑 \(f_{i, k}, f_{k +1, j}\)

发现当 \(c_k \not = c_j\) 时,这种转移一定可以由下面这么转移替代:

\(f_{i, j} = \min\{f_{i, j - 1} + 1, f_{i + 1, j}\}\)

于是只要特殊考虑 \(c_k = c_j\) 的情况即可,记录个前驱简单枚举即可。

\(\color{blueviolet}{CF878D}\)

我真不理解,以后再理解。

\(\color{blueviolet}{CF1063C}\)

真没啥水平,放一条直线上二分即可。

\(\color{blueviolet}{P2501}\)

非常好题目。

\(a_i \leftarrow a_i - i\),变成不降问题。

第一个限制是最少需要改变多少数,等价于最多不改变多少数字,求一个最长不降子序列即可。

考虑一个最长不下降子序列,如何调整使得满足第二个限制,设 \(u, v\) 为当前最长不下降子序列的两个元素,两者之间的元素为 \(p_1, p_2, \dots, p_t\)。最优方案一定是存在一个 \(k\) 使 \(p_1 \leftarrow u, p2 \leftarrow u, \dots, p_k \leftarrow u, p_{k + 1} \leftarrow v, p_{k + 2} \leftarrow v, \dots, p_t \leftarrow v\),这样调整,可以证明任意一种方案都可以调整为当前这种方案并且不劣。

考虑记录每个位置最长不下降子序列的转移来源,每次对于 \(v\),枚举 \(u\),再枚举 \(k\) 进行调整即可。

\(\color{blueviolet}{P2470}\)

添加一个 M 本质上相当于重置循环节开头,因为不能嵌套所以记录一下是否出现 M 然后区间 DP 即可。

\(\color{blueviolet}{P5574}\)

对于决策单调性上一个分治处理即可,逆序对可以用树状数组动态维护,搞一个像莫队那样的指针即可,复杂度是对的。

\(\color{blueviolet}{P2518}\)

需要动态记录每个数出现次数(除了 \(0\)),用 vector 即可,然后普通的数位 DP。

\(\color{blueviolet}{P4127}\)

枚举模数,要求 DP 后余数为 \(0\),普通的数位 DP 即可。

\(\color{blueviolet}{P3311}\)

先套个 AC 自动机上来,然后在 Trie 树上做个数位 DP 即可。

\(2023.12.25-2023.12.31\)

\(\color{blueviolet}{P3643}\)

首先考虑暴力 DP了,设 \(f_{i, j}\) 表示强制学校 \(i\) 参赛,考虑前缀学校,其派出 \(j\) 一辆划艇的方案数。

数量级太大了,考虑其中有一些状态本质相同,于是可以先离散化一下,对于离散化中的数据,一段一段是本质相同的,于是上述状态的 \(j\) 表示派出划艇数量在第 \(j\) 段。

于是有:

\(f_{i,j}=\begin{cases}\sum_{pos=0}^{i-1}\sum_{k=0}^{j-1}f_{pos,k}\times\binom{m+L_j-1}{m}&[t_j,t_{j+1})\subseteq[a_i,b_i)\\0&\mathrm{otherwise}\end{cases}\)

其中 \(m\) 表示 \((pos, i]\) 中可以派出 \([t_j,t_{j+1})\) 辆划艇的学校数量,\(L_j = t_{j + 1} - t_j\) 即这一段长度。

考虑以下枚举方式进行暴力,\(i, j, k, pos\),其中 \(pos\) 倒序枚举。

\(pos\) 倒序枚举的时候可以从上一次枚举继承一部分组合数以及 \(m\) 的运算。

这样发现 \(k\) 是无意义的,可以在第二维上做一个前缀和优化,然后就做完了。

\(\color{blueviolet}{CF1156F}\)

DP 状态是显然的,设 \(f_{i, j}\) 表示第 \(i\) 次抽卡抽取到 \(j\) 的概率,有转移:

\(f_{i, j} = \sum \limits_{k = 0}^{j - 1} f_{i - 1, k} \times \frac{buc_j}{n - i + 1}\)

这个东西后面的系数显然可以提出来然后前缀和优化转移。

然后考虑统计答案,每次转移的时候记录一个下一次抽取和这一次抽到一样的概率累加到答案上即可。

\(\color{blueviolet}{CF1542E2}\)

非常有水平的题。

先枚举相同前缀长度,然后钦定下一位不同,于是问题转化为对于每个 \(i\)\(i\) 阶排列对 \((p, q)\) 的数量,使得 \(p_1 < q_1\)\(\pi(p) > \pi(q)\)。其中 \(\pi(x)\) 为序列 \(x\) 的逆序对数。

\(f_{i, j}\) 表示 \(i\) 阶排列 \(\pi(p) - \pi(q) = j\)。转移考虑枚举开头元素 \(p_1, p_2\) 有:

\(f_{i, j} = \sum\limits_{p_1 = 1} ^ {i} \sum\limits_{q_1 = 1} ^ i f_{i - 1, j - p_1 + q_1}\)

值得注意的是下标可能为负,所以做的时候要整体位移一段。

答案即:

\(\sum\limits_{p_1 = 1} ^ i \sum\limits_{q_1 = p_1 + 1} ^ i f_{i - 1, j - p_1 + q_1}\)

发现只关心开头元素差值,考虑枚举差值 \(d = p_1 - q_1\),则有:

\(f_{i, j} = \sum\limits_{|d| < i} f_{i - 1, j - d} (i - |d|)\)

\(d\) 按正负分开:

\(f_{i, j} = \sum\limits_{d = 1} ^ {i} f_{i - 1, j + d} (i - d) + \sum\limits_{d = 0} ^ {i - 1} f_{i - 1, j - d} (i - d)\)

把前半部分拿出来做以下推导:

\(\sum\limits_{d = 1} ^ {i} i f_{i - 1, j + d} - \sum\limits_{d = 1} ^ {i} d f_{i - 1, j + d}\)
\(\sum\limits_{d = 1} ^ {i} (i + j) f_{i - 1, j + d} - \sum\limits_{d = 1} ^ {i} (j + d) f_{i - 1, j + d}\)

然后发现关于第二维做两种前缀和即可,后半部分类似。

\(\color{blueviolet}{AT\_tdpc\_string}\)

纯种 DP。

\(f_{i, j}\) 表示前 \(i\) 种字符加入后,有 \(j\) 对相邻相同字符的方案数。

新加入的字符有以下三种功能:

  1. 拆开以前相邻的相同字符。

  2. 两个组成一对相邻字符。

  3. 什么也不干。

贡献用组合数计数是简单的,直接暴力枚举上述三种字符数量进行 DP,注意上下界以及初值问题即可。

\(\color{royalblue}{CF1312D}\)

没啥水平题,一眼秒了。

先确定数字发现分组是简单的,相当于每个数字可以在左或右,最大值以及两个相同元素位置是固定的,也就是有 \(2^{n - 3}\) 种方案。

考虑选数,先从 \(m\) 个中选出 \(n - 1\) 个数,再从 \(n - 1\) 个数中去掉最大值再选一个数,贡献即 \(n - 2\)

有答案:

\(2 ^ {n - 3} \times \dbinom{m}{n - 1} \times (n - 2)\)

\(\color{blueviolet}{CF67C}\)

挺好玩的性质题。

DP状态是显然的,\(f_{i, j}\) 表示 \(a\) 串匹配前 \(i\) 个字符,\(b\) 串匹配前 \(j\) 个字符的最小代价。

前三个操作的转移是显著的,考虑第四个操作以及其代价限制起什么作用。

连续的交换不如添加和删除,唯一可以起到的作用是交换两个数,可以考虑删除中间一段,交换两头的字符,再添加中间的一段。

具体的来讲,假设现在正在处理 \(a_i, b_j\),设 \(b_j\) 最后一次出现在 \(a_1 \sim a_i\) 中的 \(x\) 位置,\(a_i\) 出现在 \(b_1 \sim b_j\)\(y\) 位置,则我们先令 \(a_1 \sim a_{x - 1}\)\(b_1 \sim b_{y - 1}\) 匹配好,然后删除 \(a_{x + 1} \sim a_{i - 1}\),交换后再添加 \(b_{y + 1} \sim b_{j - 1}\),转移是简单的。

\(\color{black}{P2605}\)

状态非常显然,\(f_{i, j}\) 表示第 \(i\) 个点选定为基站,并且总共建了 \(j\) 个基站的最小代价(只考虑前 \(i\) 个),然后就是很裸的线段树优化 DP 转移。

posted @ 2023-11-29 14:51  Eon_Sky  阅读(19)  评论(0编辑  收藏  举报