P9476 [_-0 B] 地铁

原题

人类智慧题!!!

假如没有地铁,这题就是一个非常典型的计算贡献的题。我们对每一条边看他左右子树中通过的客流量多少,对于一个边权为 w 的边,他的贡献显然为 w×S1×S2 ,其中 S1,S2 为当前边把树分成左右两部分的子树大小

现在有了地铁,使答案减少了 D

假设一个人从 A 走到 B ,路经 A,p1,p2,...,pt,Bt+2 个点,则对 D 产生的贡献是:

(wAp1wAp1)+(wp1p2wp1p2)+...+(wptBwptB)t

这个式子中的 t 看起来非常碍眼,因为我们想要考虑每个边对答案产生的贡献,但 t 显然与每条边无关,而是和这个人有没有经过铁路有关,这是我们不想要的,因此我们可以魔改一下式子:

(wAp1wAp1t)+t+(wp1p2wp1p2t)+t+...+(wptBwptBt)

这样看起来就好多了,因为 wwt 就可以看成是路径上边的贡献,而 t 就可以看成是路径上度数为 2 的点的贡献(即把所有点的点权都看成 t)

因此我们考虑每个边和每个点贡献的次数

对于一条边,计算同上,对 D 的贡献为 (wwt)×S1×S2

对于一个点,他把树分成了三个部分,如图,他的贡献为 t×S1×S3

因此我们考虑树形 dp

dpi 表示以 i 为根的子树中,链的一端为 i 的父亲,另一端在 i 的子树中的最大贡献

我们发现转移分两种情况:

  1. 链的另一端就是 i
    此时 dpi(w(i,fai)w(i,fai)t)×sizi×(Nsizi)

  2. 链的另一端在 j 点的子树内,其中 ji 的直接儿子
    此时 dpi(w(i,fai)w(i,fai)t)×sizi×(Nsizi)+t×sizj×(Nsizi)+dpj

在求完 dp 值后还没完,因为我们还没有找到答案,我们要考虑怎么更新答案。不妨设最终答案为 D

我们设地铁两个端点的 LCAr ,则有两种可能:

  1. 如果 r 是端点,则 Ddpr

  2. 如果 r 不是端点,则 Ddps+dpt+t×sizs×sizt

注意,这里读入的 t 和铁路的端点 t 并不是一个 t

对于第一种情况是很好考虑的,直接对于每个点更新一边 D 即可

但对于第二种情况,我们直接枚举 s,t 显然会超时,怎么办呢

我们再次考虑魔改一下式子:

Ddps=t×sizt×sizs+dpt

这长的想什么?像斜率优化!

y:dpt
x:t×sizt
k:sizs
b:Ddps

我们可以把他们按照 siz 排个序,然后用单调队列维护凸包

最终复杂度 O(nlogn) ,瓶颈在于排序

posted @   FOX_konata  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示