Solution Set - DP

CF101E Candies and Stones

Link&Submission.

DP 的状态设计和转移都是显然的,唯一的问题在于需要输出方案,而这题卡空间。会发现如果用 bitset 存下所有位置的转移,空间刚好多了一点点。所以考虑分两次,第一次只存后 10000 行的转移,然后从最终状态倒退回 n10000 行,再重做 DP 求出前面行的转移即可。DP 数组显然可以优化到一维。

CF67C Sequence of Balls

Link&Submission.

比较套路,定义 dpi,j 为 A 的前 i 个和 B 的前 j 个匹配的方案数。转移如下:

  • 插入,dpi,j1+tidpi,j
  • 删除,dpi1,j+tddpi,j
  • 替换,dpi1,j1+tr×[aibj]dpi,j
  • 交换,由题目中给出的条件 2teti+td 可以知道两次交换如果相交是不优的,所以方案应该是先删除要交换的两个字符中间的字符,再把它们插入回去。那么转移就是 dpp1,p2+(ip12)×td+(jp22)×ti+tedpi,j。这里的 p1 是满足 a[p1+1]==b[j] 的最大 p1p2 类似。容易发现这样是最优的。

可以预处理 p1,p2

CF48G Galaxy Union

Link&Submission.

找到基环树的环,删掉换边得到一个森林,包含若干棵树 T1,,Tk。一个点 uTi 的答案由几部分组成:

  • uvTi 的点的距离和。这可以对每棵树换根跑出来,时间 O(n)
  • Tj 的根 rtjTj 内的点的距离和,ji。在上一步就求出来了。
  • Ti 的根 rti 和其它环上的点的距离与子树大小乘积的和。对于这个问题,我们提出环做一次扫描,维护一条分界边,当前起点到任何环上点的最短路不跨过分解边。当起点移动一条边时,这条边的贡献变化。当分解边跨过一个点时,这个点的贡献变化。预处理前缀和可以 O(1) 维护变化。扫描起点,分解边的变化是单调的。

时间复杂度 O(n)

CF11E Forward, march!

Link&Submission.

考虑二分答案,则相当于一次正确操作权值 1,一次增加操作权值 mid,判断最大权值是否为正即可。

定义 dpi,0/1 表示已经考虑了前 i 位,当前步骤是 L/R 的最大权值。转移很好写,只要考虑是否添加 X。

注意先预处理出所有连续跨同一步的情况。还有就是如果操作序列的开头结尾都是 R,应该在开头加 X;如果开头结尾都是 L,应该在结尾加 X。

CF321D Ciel and Flipboard

Link&Submission.

感觉没有黑。

显然一个子矩形只有翻转奇数次和偶数次的区别。奇数次在左上角标 1,偶数次在左上角标 1,得到一个 m×m1,1 矩阵。最终每个位置的权值就是以它为右下角的 m×m 矩阵的乘积乘以这个位置上的初始值。会发现有贡献的子矩阵是上面这个 m×m 的子矩阵中包含至少一个角落的所有矩阵。

显然这个 m×m 的矩阵和它的前缀积矩阵 S 一一对应。几种贡献为:Si,jAi,j,Si,jSm,jAi+m,j,Si,jSi,mAi,j+m,Si,jSi,mSm,jSm,mAi+m,j+m

可以二进制枚举 Sm,1m,假设还确定了 S1m1,m,那么每个 Si,j 都乘一个常数,用这个常数的绝对值贡献进去就行。而不同的 Si,m 互不影响,所以枚举 Si,m=±1 计算,取较大值即可。

CF251E Tree and Table

Link&Submission.

先解决一个特殊情形:链。运用简单的组合计数知识得到答案是 2(n1)n+4

对于一般情形,如果有点的度大于 3 则无解。剩下的情形中,我们找出一个度为 3 的点作为根,进行树形DP。

fi 表示以 i 为根的子树,放在大小适合的 2×m 矩形中,i 放在左上角的方案数。gi,j 表示分别以 i,j 为根的两棵子树,放在适合的矩形中,i,j 分别放在左上角和左下角的方案数。考虑 fi,j 的转移。

  • i 有两个儿子 u,v。分别尝试它们能不能放在左下角。以 u 为例,若 u 没有儿子,则贡献 fv;若 u 有一个儿子 x,贡献为 gx,v;若 u 有两个儿子,贡献 0
  • i 有一个儿子 u。两种情形:一是 u 放在左下角,仅当 u 有唯一儿子 v 时贡献 fv;二是 u 放在 i 右边,那这条链必须一直向右延申,到某个位置 v 出现分支(即有两个儿子 x,y)。此时必须有一个儿子(如 x)负责回头。当然,也有可能没有分支一路到底,此时判断奇偶性,贡献为 01
    这个负责回头的儿子可能是自己回头,也可能它有两个儿子 w,z,其中一个负责回头。回头指填满下面一行的左边,这要求其往下恰好是一条长度为某个值的链。如果是儿子(如 w)回头,则贡献为 gz,y;如果是自己回头(即只有一个儿子),则贡献为 fy

gi,j,考虑 i,j 的儿子数目 c,d。若 c,d 中有 2gi,j=0;若都为 1gi,j=gsoni,sonj;若某一个(如 c)为 1,则 gi,j=fsonj;若都为 0gi,j=1

然而我们肯定不能把整个 g 数组求出来。分析上面的过程,实际上我们把 i,j 都往下找,找到第一个儿子数目不为 1 的点 x,y。如果 x,y 中较浅的一个儿子数目为 2gi,j=0,否则,不妨 x 较浅,让 j 往下走相应的深度,gi,j 就等于走到的点的 f 值。向下走的过程可以倍增预处理。

实现时,第一遍dfs预处理出一层儿子和深度,然后倍增预处理,再进行DP。g 写成函数,过程中调用的次数和 n 同阶,所以时间 O(nlogn)

接下来统计答案。设 x,y,z 为根 rt 的三个儿子,x 的度最大。

  • x 的度为 3,考虑两种情形:一是 rtx 同列,设 x 的两个儿子为 u,v,则贡献为 gu,ygv,z+gu,zgv,y;二是 rtx 同行,此时一半为 fx,另一半类似上面第一种转移。
  • x 的度小于 3,则 x,y,z 都至多一个儿子。考虑谁和 rt 同列,以及它的子树往哪一边靠(可能没有,要判),总共 6 种情形。累加入答案即可。

不要忘记,根据对称性,答案还要乘 4

CF331E2 Deja Vu

Link&Submission.

考虑一条路径,称它经过的点构成的序列为点列,它经过的边上标记的点连成的序列为边列。

注意到,如果一条路径(不一定好)走到某处,边列长于点列,那么我们就知道接下来应该往哪里走了。然后,在这个走的过程中,由于点列的长度每一步只增加一,所以(如果能产生好路径)一定有某一步之后点列长度恰好等于边列长度,也就产生了好路径。

定义 dpi,j 为终点为 i,长为 j 的好路径数目。考虑转移,从 dpi,j 开始,往后走一条 i 的出边 (i,u),有两种可能:

  • 这条边上的序列长度为 0。那么再想产生好路径,就要从 u 开始找一条好路径。为了避免重复,我们需要保证新的这条好路径不存在一个前缀也是好路径。
  • 这条边上长度的序列大于 0。那么此时边列长度大于等于点列,就知道接下来应该怎么走了(或者已经是好路径了)。根据上面的推理,第一次走到点列等于边列就有了好路径。这时的转移不会重复。

剩下的问题就是预处理 fi,j,k 表示从 ij,长度为 k,且没有真前缀是好路径的好路径数目。

仍然是考虑点列和边列的长度关系。一开始,点列长度大 1。走若干步之后,边列长第一次大于等于点列。然后再往后走就找到了好路径。但是这样不知道该怎么走,所以换一个思路,枚举使得边列长超过点列长的边,那么这条边 (i,j) 上的序列一定包含了连续的 i,j。从这条边开始往两边走都是有方向的,走到第一个等号位置即可。

是不是还少了什么?往后走是没问题了,但是往前走不一定,第一个等号位置或许还可以再往前一点。再往前的一条边上的序列长不能是 0,否则就有真前缀了;然后就又有方向了。按照长度再做一次转移即可。

写出代码会发现时间复杂度 O(n4)

posted @   by_chance  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示