「杂题乱写」Codeforces 上 DP 乱写

作为衡中 OIer,我们要紧随 SoyTony 步伐,建设新时代 SoyTony 特色博客 .

原博客:SoyTony .

CF607B Zuma

给一个长度为 \(n\) 的字符串 \(a\),每次可以选一个回文子串消掉,问至少消几次能消完 .

\(1\le|\Sigma|\le n\le 500\) .

魔幻区间 DP .

首先处理长度不大于 \(2\) 的答案,这是平凡的 .

然后考虑如果对于 \(a_l = a_r\),那么消除 \([l+1,r-1]\) 的时候肯定能顺便把 \(a_l,a_r\) 也消了,否则枚举断点拆成两半转移即可 .

时间复杂度 \(\Theta(n^3)\) .

CF178F Representative Sampling

\(n\) 个字符串,要求选出一个 \(k\) 元子集 \(\{a_k\}\),使得

\[\sum_{i=1}^n\sum_{j=i+1}^n|\operatorname{lcp}(a_i,a_j)| \]

最大 .

\(n\le 2000\),字符串长度不大于 \(500\) .

(F2:\(n\le 100\))考虑 Trie 树上 DP,令 \(dp_{u,k}\) 表示 \(u\) 的子树选了 \(k\) 个串的答案,转移是树形背包,时间复杂度 \(\Theta(ck)\)\(c\) 是 Trie 树点数,无法得到满分 .

把树压缩一下,留下表示字符串末尾节点的虚树,这样就有 \(c=\Theta(n)\),时间复杂度即为 \(\Theta(nk)\),可以通过 .

CF1774E Two Chess Pieces

\(n\) 个点的树上两个指针 A, B,要求任意时刻 A, B 间距离不超过 \(d\) .

A,B 有一些必须经过的结点,每次操作可以将 A 或 B 移动一步,问 A, B 从根节点出发遍历所有点后回到根的最小步数 .

\(2\le d\le n\le 2\times 10^5\) .

处理每个点 \(u\) 子树内最深结点深度 \(f(u)\),维护 \(dp_{1,u}\) 表示只靠一个指针环游 \(u\) 子树内结点的答案,\(dp_{2,u}\) 表示两个指针环游 \(u\) 子树内的答案 .

对于每条边 \((u,v)\),如果 \(f(v)-\operatorname{dep}(u)>d\) 或者 \(u\) 子树内有 A, B 都要去的点,那么对于这条边的 \(dp_{2,u}\) 就必须有 A,B 移动的四次贡献(这时候 \(dp_{1,u}\) 未定义,不过也不需要可以不管),否则可以借助 \(dp_{1,u}\) 的答案走两步转移到祖先(此时一定可以只用一个指针完成任务,另一个不用动).

实际操作的时候可以把每个 \(dp_1\) 加一,比较好转 .

时间复杂度 \(\Theta(n)\) .

CF1783D Different Arrays

给一个序列 \(\{a_n\}\),对于所有 \(1<i<n\),执行操作 \(a_{i+1}\gets a_{i+1}+a_i\)\(a_{i-1}\gets a_{i-1}-a_i\)\(a_{i+1}\gets a_{i+1}-a_i\)\(a_{i-1}\gets a_{i-1}+a_i\) .

问最后可能有多少种不同的序列 .

\(1\le n,a_i\le 300\) .

\(dp_{i,j}\) 表示到第 \(i\) 个操作前 \(a_i=j\) 的答案,转移的时候对于 \(j=0\) 两种操作生成序列相同否则不同 .

这样即可做到 \(\Theta(nV)\) .

CF1771D Hossam and (sub-)palindromic tree

给一棵 \(n\) 个点的树,每个点上有一个字符,找一条最长的链使得链上节点上的字符顺次链接为回文串 .

\(\displaystyle\sum n\le 2\times 10^3\) .

考虑序列上的问题就是区间 DP,令 \(dp_{l,r}\)\([l,r]\) 的答案,则

\[dp_{l,r}=\max\{dp_{l+1,r},dp_{l,r-1},dp_{l+1,r-1}+2[s_l=s_r]\} \]

上树的话考虑每条链 \(u,v\) 往里缩一格得到的转移即可 .

转移点可以倍增预处理,时间复杂度 \(\Theta(n^2\log n)\) .

CF1761D Carry Bit

给两个整数 \(n,k\),问有多少 \((a,b)\) 满足 \(0\le a,b<2^n\)\(a+b\) 二进制下的进位数为 \(k\) .

\(0<k\le n\le 10^6\)

考虑 DP,\(dp_{i,j,0/1}\) 表示 \(1\dots i\) 共进了 \(j\) 位,最后进位 / 未进位的方案数 .

经过朴素的分类讨论可以得到转移:

\[\begin{aligned}&dp_{i,j,0}=3\cdot dp_{i-1,j,0}+dp_{i-1,j-1,1}\\&dp_{i,j,0}=3\cdot dp_{i-1,j-1,1}+dp_{i-1,j,0}\end{aligned} \]

观察可以发现,如果对于每一位的进位 / 未进位已经钦定完毕,那么只有相邻状态不一样的位置会产生贡献,这个等价于连续段数量 .

于是考虑枚举连续段数量 \(i\),然后讨论首位是否进位后插板法即可 .

时间复杂度 \(\Theta(n)\) .

需要注意一下 corner case .

CF1743E FTL

有两艘飞船,第 \(i\) 艘飞船的攻击力为 \(p_i\),每一次攻击的充能时间为 \(t_i\),一开始两艘飞船没有充能 .

现在要打败敌方飞船,敌方飞船的血量为 \(h\),防御力为 \(s\) . 对于一次攻击力为 \(P\) 的攻击,敌方飞船的血量会减少 \((P-s)\) . 攻击的攻击力为所有参与攻击的飞船攻击力之和 .

敌方飞船血量不大于 \(0\) 即被打败,问最少需要多少时间能够打败敌方飞船 .

\(2\le h,p_1,p_2\le 5000\) .

考虑两个飞船同时攻击就相当于回复到初始状态,于是 DP 处理对于每个 \(i\in[0,h]\) 处理最后一次两个一起攻击前面都不一起攻击打掉 \(i\) 格血的答案 .

然后 DP 统计一下把上面的东西组合起来的答案即可 .

时间复杂度 \(\Theta(h^2)\) .


(注:不会更新,纯属搞笑用)

posted @ 2023-02-19 18:41  Jijidawang  阅读(120)  评论(1编辑  收藏  举报
😅​