题目传送门
讲真,第一眼看上去以为是水题…
于是一发一共能观测到多少人就上去了…
然后极其黑历史,成就达成第一次看错题…
请各位注意,输出每个节点的观察员可以看到多少人!!!
然后怎么做…
因为每个人走的是最近路径,因此每个人走的路径应为
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
S,T对答案的影响已经结束,将向下桶里
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
[NOIP] [LCA] NOIP2016Day1 天天爱跑步
最新推荐文章于 2022-05-01 08:22:29 发布