[WC2018] 通道
genlib 真是太好用了。
题目链接: [WC2018] 通道 。
题目描述:
给你三棵树 T1,T2,T3 。
求 a,bmax{dist1(a,b)+dist2(a,b)+dist3(a,b)} 。
n≤105 。
这一看就是一个类似树的直径的东西。于是考虑边分治。在 T1 上边分治后会得到左右两个点集,不妨记为 A,B 。设这些点到其中一个中心边的端点的距离为 vala ,那么就有 dist1(a,b)=vala+valb ,其中 a∈A,b∈B 。
此时式子变为最大化 vala+valb+dist2(a,b)+dist3(a,b) ,此时可以在 T2 上继续边分治,然后在 T3 上建立虚树,获得 O(nlog2n) 的复杂度以及 O(∞) 的常数,不可取。所以只能将 A,B 点集中的点在 T2 中建立虚树。设某一点 a 到虚树根节点的距离为 da ,那么就有 dist2(a,b)=da+db−2dlca(a,b) 。
然后,自然的,在虚树上枚举他们的 lca ,设为 L ,那么式子变为最大化 (vala+da)+(valb+db)+dist3(a,b)−2dL 。其中 dL 是常数,可以忽略。那么剩下的就是一个类似于带权树的直径的东西。这个东西可以通过对于 T3 的每个节点 i ,新建一条边连向 i 和虚节点 i+n ,边权为 vali+di ,然后就变成了最大化 dist3′(a,b) ,这是一个标准的树的直径问题。但是有 a∈A,b∈B 的限制,我们必须在 O(1) 或 O(logn) 的复杂度内解决。
由于边带正权,那么有如下定理:
对于点集 A,B ,树上 A∪B 的直径的端点必然是 A 直径的端点和 B 直径的端点中的两个。
那么只需要合并儿子贡献就行了。
特别的,统计答案应该在合并儿子贡献时统计,不然无法保证 lca 为 L 。合并儿子需要枚举 6 种情况,统计答案要枚举 8 种情况,都枚举到就行了。
代码写了 6KB ,不放了。