天天看点

题解[NOIP2016 提高组] 天天爱跑步

算是NOIP中比较麻烦的题了,看题解感觉处理的很巧妙

题意就不再赘述了,刚开始的想法是遍历枚举每一条路径,但是无论如何这样做的复杂度最坏都有O(nm)

所以尝试换一种方法,从观察员下手,对于每一个观察员,我们只需要找到每一条路径带给他的贡献

那这个贡献怎么求呢?

对于每一条路径(u,v),我们都可以将它拆为 u->lca 与 lca ->v

假设观察员的位置p在 u-> lca 上,当depth[u]+w[p]=depth[p]时才会有贡献

而当p在 lca->v 上时,只有dist(u,v)-(depth[v]-depth[p])=w[p],即dist(u,v)-depth[v]=w[p]-depth[p]时才有贡献

然后是统计贡献,如果我们在统计贡献时也一个一个去计算,那么复杂度就又上去了,所以这个时候可以用一个桶来处理,

这也是这道题比较巧妙的一点,

先看u->lca,对于点x,我们将它贡献的答案存在cnt[depth[x]]里,对于这条路径上的点p,更新答案就只需要加上cnt[depth[p]+w[p]]

对于lca->v,我们就将答案贡献存在cnt[dist(u,v)-depth[v]]里,同理对于p,更新答案加上cnt[w[p]-depth[p]]

然后是这道题中的一些细节部分,结合代码理解