看到厦门的榜特别惨,比较好奇这套题。
题意:多组样例,一颗带有点权的无根树,定义两点路径D为其简单路径上的点的数量,定义MAX为其路径上的点权最大,MIN为其路径上的点权最小,现要你求最小的 D-MAX+MIN。 数据量总的节点数量,及最大点权均不超过
1
0
6
10^6
106
想了很久,看了一句话题解也只想到一个 O ( n ∗ l o g 2 n ∗ l o g 2 n ) O(n*log_2n*log_2n) O(n∗log2n∗log2n)的做法,就是每次划分子树后,枚举一颗子树中的路径,且枚举过程中,记录当前枚举路径的最大最小值
- 当前路径可以作为路径最大值的端点,那么就需要另一条路径的端点作为最小值,那么就相当于在另一侧中找最小值比当前路径还要小的路径中D+MIN的最小值。实现这个我们只需要实现一个可以维护前缀最小值的树状数组即可。
- 作为最小值同理。维护后缀最小。
问了橘子猫大佬后,得到了一个
O
(
n
∗
l
o
g
2
n
)
O(n*log_2n)
O(n∗log2n)的做法!
注意到路径的构成一定是 两点的路径点数-MAX+MIN。
那么这里我们只列举枚举路径作为最小值,最大值同理。
注意到 跨越重心的路径可以拆解为
D
x
+
M
I
N
x
+
D
y
−
M
A
X
y
Dx+MINx+Dy-MAXy
Dx+MINx+Dy−MAXy
最开始看到那句话:“答案一定是那种最大值最小值作为路径端点的路径”的时候有点困惑,没太想清楚这里要怎么O(1)计算。
对于每条枚举过的路径,我们开一个变量MAXX来表示最小的
D
−
M
A
X
D-MAX
D−MAX,这个直接对于每个路径端点做更新就好,不必管他是不是路径的最大值,因为如果他不是路径的最大值,那么他必定小于已经存在的最大值,那么必定他就不会使答案更优,也即不会更新MAXX,而如果他是当前路径的最大值,那么就可能更新MAXX。
并且我们枚举路径计算的时候,考虑两种情况:
- MAXX中的最大值比枚举路径的最大值要小,那么必然当我们下一次以当前子树作为重心划分的时候会得到更优解。也即若当前答案被错误的更新了,后续也一定会被重新修正!
- MAXX中的最大值比枚举路径的最大值大,那么就必定是一条合法的路径,只要更新即可。
所以我们可以直接枚举路径,计算 D + W [ u ] + M A X X − 1 D+W[u]+MAXX-1 D+W[u]+MAXX−1。
代码暂时不贴,debug还没完成