P4292 [WC2010]重建计划——一题多解, 长剖胜出

Description

请在图上找到一个长度在 [ L , R ] [L,R] [L,R]之间的路径,使得这条路径经过的所有边的权值的平均值最大。请输出这个平均值。

Solution 1: 二分+点分治+线段树

首先,我们二分答案。假设当前二分到的值为 m i d mid mid,我们将所有边权暂时减去 m i d mid mid。显然,在原图中一条边权平均值不小于 m i d mid mid的路径,等价于在新图中权值和为非负数的路径。

考虑点分治。我们扫描当前节点 n o w now now的所有儿子,维护一棵线段树,它以深度(即与 n o w now now的距离)为下标,以从对应深度的节点到 n o w now now的边权之和的最大值为节点维护的量。每加入一个深度为 p p p的节点,就需要查询区间 [ p − r i , p − l e ] [p-ri,p-le] [pri,ple]的最大值;另外还要进行一次单点修改。线段树可以胜任这样“单点修改, 区间查询最大值”的问题。

二分的复杂度为 O ( log ⁡ ( v i × 1 0 4 ) ) O(\log (v_i×10^4)) O(log(vi×104))(需要保留小数点后三位),点分治的复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),线段树维护的复杂度为 O ( log ⁡ n ) O(\log n) O(logn),总时间复杂度为 O ( n log ⁡ 2 n log ⁡ ( v i × 1 0 4 ) ) O(n \log^2 n \log (v_i×10^4)) O(nlog2nlog(vi×104)),无法通过本题。

当然,如果常数控制得很好,也许可能卡过。

Solution 2: 二分+长链剖分+线段树

我们仍然按类似Solution 1中的方法去二分答案并建立带有新点权的新树。考虑在新树上执行一次树形 d p dp dp

状态设计: d p i , j : dp_{i,j}: dpi,j: 在以 i i i为根的子树中,以 i i i为一端且长度为 j j j的路径的最大可能权值和。

我们如何进行状态转移呢?我们可以对于每一个 i i i的孩子节点 s o n son son,将它暴力合并到 i i i这里,并实时更新答案(更新答案仍然采用类似Solution 1的线段树)。这样的复杂度是 O ( n 2 log ⁡ n ) O(n^2 \log n) O(n2logn)的,无法通过。

考虑这个 d p dp dp是否可以用长链剖分来优化。我们可以先将 i i i儿子 l s ls ls直接合并起来,然后对于其他孩子去暴力合并,并实时维护一棵线段树来方便更新答案。

这样的复杂度为什么是正确的呢?考虑一个节点的非长儿子一定是一条链的顶端,所以一个节点只会对这条链顶端的父亲产生复杂度 O ( log ⁡ n ) O(\log n) O(logn)的维护线段树的代价。每个节点都贡献了 1 1 1次,所以时间复杂度就是 O ( n log ⁡ n ) O(n \log n) O(nlogn)的。

可以使用 v e c t o r vector vector或指针来保证空间复杂度的正确性。

总时间复杂度 O ( n log ⁡ ( v i × 1 0 4 ) log ⁡ n ) O(n \log (v_i×10^4) \log n) O(nlog(vi×104)logn),由于本题时限为 4 s 4s 4s,可以轻松通过。

Summary

由于点分治本身是一种折半分治,它的复杂度一定是带一个 log ⁡ \log log的。而长链剖分不同,它可以把 d p dp dp成功优化到 O ( n ) O(n) O(n)。一个 log ⁡ \log log,造成了这两种做法“一个可过,一个不可过”的差异。

本题考查了对线段树, d p dp dp以及长链剖分的技巧,是一道不可多得的好题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值