Description
有一棵树,
d(u,v)
表示
u
,
v
之间最短距离。
现在要求一个排列
pi
,使得
∑ni=1d(i,pi)
最大,同时满足最大时字典序最小。
Solution
对于一条边,我们肯定希望它被计算尽量多次,若左右端点连出去的节点个数分别为
x
,
y
,那么该边的最大贡献为
val×min(x,y)×2
,于是选择重心来构造恰好能满足(如下)。
先把式子写出来:
∑i=1nd(i,pi)=∑i=1n(depi+deppi−2deplca(i,pi))=2∑i=1ndepi−∑i=1n2deplca(i,pi)
选定一个根,每对点不能出现在根直接连下去的同一棵子树中。
对于根直接连向的每棵子树,设大小为
k
,子树内的点可以和子树外的
n−k
个点匹配,同时这
k
个点都要被匹配,那么
k≤n−k
,
k≤⌊n2⌋
。那么选择树的重心为根就能满足。
于是我们抛开权值,只用找字典序最小的排列。
对于当前将要匹配
i
,要找到最小的
pi
,同时满足不同根直属子树。设当前子树有
x
个未匹配的(即编号大于
i
的个数),以及有
y
个未被匹配的(在这棵子树中不出现在已确定
pi
中的编号),那么满足
x≤n−i+1−y
,即
x+y≤n−i+1
。对于一棵子树满足
x+y=n−i+1
,那么当
i+1
时,
x
或
y
要减
1
。此时分两种情况:
-
i
在这棵子树内,那么可以直接和子树外的匹配,使得
x−1
。
-
i
不在这棵子树内,那么必须选择这棵子树内的匹配,使得
y−1
。
若当前没有满足等式的情况,直接选择与
i
不同子树匹配即可。
(对于每次匹配,选择编号最小的)
至于重心,当满足等式时,那么必须选择那棵子树,如不满足,则匹配最小编号(可以匹配自己)。
于是可以用线段树维护,对每个子树开一个位置,存储
x
,
y
,以及被匹配了多少个。