1 条题解
-
0
题目重述(E. Kia Bakes a Cake)
我们有:
- 一棵 个节点的树
- 一个长度为 的二进制串 , 表示节点 被选中
被选中的节点集合记为 ,
根据被选中的节点 构造一个完全图:
- 节点集 =
- 边权 = 树 中 到 的唯一路径上的边数(即树上距离)
一条路径 (顶点来自 ) 是 nice,如果: [ 2 \cdot w(v_i, v_{i+1}) \le w(v_{i+1}, v_{i+2}) \quad \text{对所有 } 1 \le i \le m-2 ]
即:路径上每一条边的权值至少是上一条边的两倍(严格来说,至少两倍)。
对每个 ,要求:从 出发的 nice 简单路径,最长能有多长(即 的最大值)。
若 ,输出 。
1. 问题转化与关键观察
1.1 树上距离
树上两点距离 = 它们唯一路径上的边数。
因为树是连通的简单图,没有环,所以 可以快速计算。1.2 Nice 路径的条件
设边权序列为 ,其中 。
nice 条件: [ d_{i+1} \ge 2 \cdot d_i \quad \forall i ]
即权值至少翻倍增长。
1.3 权值的范围
树上任意两点的距离 ≤ 。
所以 。但翻倍条件意味着最大长度是 级别(大约 )。因此,实际上 ,因为翻倍太快,很快就超出 了。
2. 动态规划思路(分层 DP)
设 表示:从 出发,存在一条长度为 的 nice 路径(即 个节点),且该路径的第一条边权值 某个上界?
但标程里 的定义是:从 出发的最大 nice 路径长度?不,是 = 以 为起点,长度为 的 nice 路径的最大可能步数?其实标程里 存的是最大长度(顶点数)。关键:
= 以 为起点,nice 路径最大能到达的距离(步数?节点数?)。
看标程输出时:对每个 ,找最大的 使得 ,然后输出 (路径节点数)。所以 应该是路径的长度(边数)?其实他直接输出 ,那 就是路径的边数 - 1?其实 是步数级别。为了不混淆,我们直接按标程逻辑:
如果 ,否则 。
这里 只是一个很大的初始值,表示从 可以走至少 0 步(起点)。然后迭代:从 计算 ,表示从 出发,nice 路径中第一条边权值在某个范围内。
3. 树形 DP + 重心分解
3.1 树上 DP 难点
nice 路径可以跨越不同子树,需要处理“两条边的权值比较”。
受树结构影响,不是简单的深度差。但 ,其中 是深度。
如果两条边为 和 ,nice 条件: [ 2\big(h[a] + h[b] - 2h[lca(a,b)]\big) \le h[b] + h[c] - 2h[lca(b,c)] ] 这很复杂。
解决办法:用重心分解。
对每个子树的根(重心),将来自不同子树的点配对,在重心处计算两条边权值。
3.2 中心分解的目的
以重心 为分界点,路径 :
如果 和 在不同子树,?不一定,因为 是重心,但 可能和 有不同 LCA。
这样还是复杂。标程用的方法是:
- 对每个重心 ,跑 DFS,对当前子树记录当前节点 的深度 ,以及 从 出发的最大步数。
- 但 其实是 的值,表示从 出发到某点的最大步数。
这样,对于边 和 ,nice 条件: [ 2 \cdot w(g,v) \le w(v,u) ] (如果 是 )。但 与 的 LCA 可能不是 ,所以 不是简单的 。
所以标程用了更巧妙的处理:
在重心 处,给每个子树 的节点 标记 ,然后对 ,我们想找之前子树的节点 满足 ?不是,其实是 ? 如果 是 LCA 的话,yes。但为了简单,我们可以先接受标程方法:通过一边 DFS 记录后缀数组,对每个 ,找之前子树中深度满足 的最大值对应的 。
4. 算法步骤总览
- 初始化 如果 ,否则 。
- 对每个层次 到 :
- 对每个节点 设置 (路径最大长度)。
- 以 数组为权值,跑重心分解,用 DFS 分阶段更新 :
- 在重心 处,对每个子树 DFS,记录每个节点 的 和 。
- 对某个 ,找之前子树里满足 的 中, 最大。
- 用后缀数组维护这个“最大值”。
- 重复直到 对大部分 。
- 最后输出:对每个 ,找最大的 使 ,输出 ,否则 。
5. 复杂度
重心分解:
每层跑 DFS:
层数
总复杂度 , 可接受。
6. 结论
标程通过多阶段 DP + 重心分解,将条件 转化为: 在重心 处,对节点 ,要找到之前子树的一个节点 ,满足 ,且 最大,这样 带某种约束。
最终输出每个点的最大可走步数 。
7. 示例验证
以第一个样例 链 , 为例,选的点是 2,3,4,5。
从 2 出发: 3(1) → 4(1) → 5(1) 路径 2-3-4-5 长度 3(边权 1,1,1)不满足 double。
但 2→4(2) 不行,因为第一次边权 1,第二次要≥2,可能 2→4(2) 然后 4→5(1)<2×无。
实际上最长 nice 路径 = 3 个点(样例输出 3),符合。
- 1
信息
- ID
- 6687
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者