1 条题解
-
0
自动搬运
来自洛谷,原作者为

AFewSuns
弱省弱校蒟蒻,tcl,zbl搬运于
2025-08-24 22:53:55,当前版本为作者最后更新于2024-01-16 17:37:53,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
终于加强了,很高兴!来水一篇题解。
题目大意
给定一颗 个点的树,节点编号为 。
边有边权,边权为 或 或不确定。
你要给每条未被确定边权的边确定一个 或 的边权,然后从树上取出若干条有向路径,使得这些链两两之间满足边不相交。
然后你会把这些路径插入一颗 01-Trie,你希望最大化这颗 01-Trie 上的节点数。需要输出方案。
。
题目分析
先考虑如何做 。
拿出树上的每一条有向路径,将它们按照字典序排序,那么原问题变成从中选出若干条边不相交的路径,它们的权值为长度之和减去相邻两项 ,求权值最大值。
直接从前往后 dp,设 表示只考虑前 条路径,选了第 条路径,且当前选取的路径边集并为 的最大权值。转移时枚举上一个选的是什么,时间复杂度 。
设字典序第 小的字符串为 ,那么 $\operatorname{lcp}(s_i,s_j)=\min\limits_{i \leq k < j}{\operatorname{lcp}(s_k,s_{k+1})}$。于是就可以一步步转移了,设 表示考虑了前 条路径,选取的边集并为 ,且当前路径与上一个选择的路径的 为 的答案。转移如下:
-
$f_{i-1,S,j} \to f_{i,S,\min(j,\operatorname{lcp}(s_{i-1},s_i))}$,预转移,处理一下 ;
-
$f_{i-1,S,j}+len_i-j \to f_{i,S\cup E_i,len_i}(S\cap E_i= \emptyset)$,表示选第 条路径,其中 表示第 条路径的边集, 表示第 条路径的字符串长度。
时间复杂度 ,需要滚动数组优化空间。字符串排序直接塞 trie 里就行了。
然后考虑 。
当所有 时,每条边都是确定的,所以总共只会有 个串;而当存在 时,需要枚举边集的所有情况,这样可能会有 个串。
实际上只会有 个串。考虑剥叶子,第一个次剥的叶子最多往外连 个串,乘 是因为路径有向。而第二次剥的叶子最多往外连 个串,以此类推,所以最后不会超过 个串,即 。
然后优化一下转移,第一维完全可以不记,让 数组自转:
-
$f_{S,j} \to f_{S,\operatorname{lcp}(s_{i-1},s_i)}(j>\operatorname{lcp}(s_{i-1},s_i))$
-
$f_{S/E_i,j}+len_i-j \to f_{S,len_i}(E_i \subseteq S)$
当然 还是要枚举的,这样就不担心空间了。考虑分析时间复杂度。
对于第 部分,考虑树上一条长度为 的路径 ,它中间最多会产生 个串,其中每个串都要枚举 个超集,于是它们的总转移时间复杂度为 。有 对 ,所以总转移时间复杂度就是 的。
对于第 部分,考虑只保留有用的 dp 状态。将每次通过第 步转移得到的 dp 状态为“关键状态”,由上面可知“关键状态”只有 个,而每个关键状态经过第 步转移时第二维至少减 ,所以最多经过 次第一步转移,于是总转移时间复杂度就是 的了!
大概需要精细实现,当然不那么精细也可以,毕竟卡不满。
之后考虑 ,即如何构造方案。
显然不能开一个 的数组记录从哪转移过来的,不然就又退化了。
于是考虑用一个操作栈来维护有效的 dp 转移,之后从后往前推就可以得到方案了。
直接记录的空间复杂度为 ,不可接受。考虑再分析一下有效状态数。
对于转移的第 部分,容易发现在枚举超集 后可以不用对每个 都尝试转移 ,直接取最大值记录在栈里就行了,空间复杂度 ;
而对于第 部分,考虑树上一条长度为 的路径 ,最坏情况下中间会有 个串,其分布在 trie 树上的第 层。模拟一下这些串在第 部分贡献的转移复杂度,发现在遍历每个串的时候会先转移到所有 ,其中 为这条路径的超集;之后根据先前的复杂度分析,这些 最多在第 部分转移 次,于是就有先前分析的复杂度。
实际上,对于 trie 树第 层的前两个节点,遍历完它们之后,它们转移到的“关键状态”是完全相等的!换句话说,由于 dp 转移是取 ,所以对于每个 ,这两个节点对应的“关键状态”都是 ,通过取 合并到一个状态了,于是它们总的复杂度贡献是 。
同理,对于 trie 树上第 层的一个节点,它下面有 个第 层的节点,这些节点对应的“关键状态”在第二维减到 的时候就全合并成一个 dp 状态了(对不同的超集 而言)。于是实际上 的这些串在第 部分贡献的总复杂度为它们在 trie 上的虚树大小(对不同的超集 而言),即 。而总共有 个超集,于是时间复杂度就是 ,所有 的总时间复杂度就是 ,空间复杂度也就变成 的了。
时间复杂度 ,空间复杂度 。实际上栈的大小大概开 就够了,然后时间空间复杂度写得没那么精细也能过。
以上是原题部分,考虑继续优化。
不难发现现在唯一的复杂度瓶颈在于第 步转移,需要枚举超集 后再枚举 进行转移。但其实只需要对于每个 ,维护出 表示 最大的 就行了,由于 dp 值只会变大,所以是很好维护的。时空复杂度 。
不难精细实现。栈的大小开 就够了。
一些剪枝:对 trie 树上每个节点的边集去重;不难证明一定存在最优方案使得每条链都有端点是叶子。
-
- 1
信息
- ID
- 9695
- 时间
- 7000ms
- 内存
- 2048MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者