[NOIP] [LCA] NOIP2016Day1 天天爱跑步

题目传送门
讲真,第一眼看上去以为是水题…
于是一发一共能观测到多少人就上去了…
然后极其黑历史,成就达成第一次看错题…
请各位注意,输出每个节点的观察员可以看到多少人!!!
然后怎么做…
因为每个人走的是最近路径,因此每个人走的路径应为 S − > lca ( S , T ) − > T S->\text{lca}(S,T)->T S>lca(S,T)>T,这样,每个人的路径就可以分为两段, S − > lca ( S , T ) S->\text{lca}(S,T) S>lca(S,T) lca ( S , T ) − > T \text{lca}(S,T)->T lca(S,T)>T了。
那么, x x x节点的观测者能观测到什么呢?
对于 x x x节点,既可以通过后向儿子走,也可以向父亲走,也就是 x x x落在 S − > lca ( S , T ) S->\text{lca}(S,T) S>lca(S,T)上或落在 lca ( S , T ) − > T \text{lca}(S,T)->T lca(S,T)>T上。
那么, x x x S − > lca ( S , T ) S->\text{lca}(S,T) S>lca(S,T)上时,满足 d e p [ x ] + w [ x ] = d e p [ S ] dep[x]+w[x]=dep[S] dep[x]+w[x]=dep[S]
x x x lca ( S , T ) − > T \text{lca}(S,T)->T lca(S,T)>T上时,满足 d e p [ x ] − w [ x ] = d e p [ T ] − len ( S , T ) dep[x]-w[x]=dep[T]-\text{len}(S,T) dep[x]w[x]=dep[T]len(S,T)
这样其实就是统计满足上述等式的点的个数,因为每次都是对 x x x的子树的操作,所以可以树链剖分,用差分数组维护。但是复杂度我猜 O ( m log ⁡ 2 2 n ) O(m\log_2^2n) O(mlog22n),卡常可以玩玩…
放弃树剖,发现一个性质,如果利用深搜,当 x x x点退出时,其子树都已经维护完成了…
这不废话吗?
利用这点,可以开两个桶,分别为向上的(父亲)和向下的(儿子)。统计一个深度的节点个数。
So,怎么统计这两个桶…
做到 x x x节点时,向下的桶加从 x x x点出发人数(统计儿子),向上的桶加到 x x x处结束人数。然后向下搜儿子。统计答案。
如果这样的话,答案会偏大。
当dfs过程将 lca ( S , T ) \text{lca}(S,T) lca(S,T)退出时, S , T S,T ST对答案的影响已经结束,将向下桶里 S S S深度减一个,将向上 d e p [ T ] − len ( S , T ) dep[T]-\text{len}(S,T) dep[T]len(S,T)深度减一个。如果这是一条链,该点答案减一(否则会计算重复)。
因为一定要求LCA,所以可以倍增求也可以Tarjan法求,用倍增是 O ( ( n + m ) log ⁡ 2 n ) O((n+m)\log_2 n) O((n+m)log2n)的,Tarjan是 O ( n + m ) O(n+m) O(n+m)的。
Code

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值