Orzwkr
P4220 [WC2018]通道
一眼看上去和 暴力写挂 类似,可是从两棵树变成了三棵树了。
看起来,暴力写挂好像两棵树是极限了,但是这题它满足 w 非负,所以直径是可以合并的。
还是考虑第一棵树上边分,化下式子成为
dis(rt,u)+dis(rt,v)+dep2[u]+dep2[v]−2dep2[lca2(u,v)]+dis2(a,b)于是还是考虑根据边分把两边分成两种颜色,然后在第二棵树上建立虚树来 dp 。然后考虑怎么维护当前子树内不同颜色的点在第三棵树上的直径长度加上 dis(rt,u)+dis(rt,v)+dep2[u]+dep2[v]。这个后面的权值我们加虚点挂在第三棵树每个节点的下面,于是变成了一个不同的求不同颜色的点的直径问题。但是直接维护这个不同颜色的直径端点明显是有问题的,我们可以考虑维护出两种颜色分别的点集的直径端点,这样就会很方便合并。这样做的复杂度是 O(nlog2n) 或者 O(nlogn) 。
能否类似 “暴力写挂” 一题的思路优化到 O(nlogn) 呢?
我们考虑当前式子长成这样:
dis(rt,u)+dis(rt,v)+dep2[u]+dep2[v]−2dep[lca(u,v)]+dis3(u,v)在第一棵树上建立边分树,维护当前边分点两个儿子分别在第三棵树上添加关于当前边分中心所加的虚点后的直径,也就是添加了权值为 dep2[u]+dep2[v]+dis(rt,u)+dis(rt,v) 的虚点后的直径。可以发现我们实际上没有必要把虚点给真正添加出来,因为我们求答案的时候是在第二棵树上进行边分树合并,合并的时候只需要判断四对点距离大小关系就好了。而初始化的时候由于只有一个点,是非常好初始化的。。所以我们直接合并边分树就做完了。
然后因为一个符号写反调了好久好久好久好久
暂时是 LOJ rank 4。。(不会卡常)
cpp
1 |
|