首先考虑怎么构造一个方案,首先先反过来,然后考虑对于一个起点,把不同儿子的点按照深度从小到大轮流跳。不难发现只要不存在一个子树的大小
>
n
2
>\frac{n}{2}
>2n,就一定有解。
至于构造方案,设
r
e
s
res
res为剩下的点,
m
x
mx
mx为最大的子树的大小,当前满足
r
e
s
−
m
x
≥
m
x
res-mx\ge mx
res−mx≥mx,每一次选择其他子树中最浅的没有被选择的点,那么最后一定有一个时候满足
r
e
s
−
m
x
=
m
x
res-mx=mx
res−mx=mx,然后一个简单的思路就是在
m
x
mx
mx和
r
e
s
−
m
x
res-mx
res−mx中轮流选即可。
这个部分有一点细节,比如最后轮流选要考虑一下有没有更浅的点没有选择。
现在我们需要找到重心,以及它的所有儿子,每一个点属于哪一个儿子,以及它的深度。
寻找重心的过程可以考虑从根每一次往一个
s
z
sz
sz最大的点走。
首先询问以0为根,所有点的深度。
然后从0往下面走,当前的点是
x
x
x,则找到所有
d
e
p
[
y
]
=
d
e
p
[
x
]
+
1
dep[y]=dep[x]+1
dep[y]=dep[x]+1的
y
y
y,询问它们到
x
x
x的距离,如果距离是
1
1
1那么就是
x
x
x的儿子,否则它在父亲的子树内,把
y
y
y跟
f
a
x
fa_x
fax连一条长度为
d
i
s
−
1
dis-1
dis−1的边。
之后询问儿子的
s
z
sz
sz,找到一个最大的走下去。
确认重心
x
x
x之后只需要对于
d
e
p
[
y
]
>
d
e
p
[
x
]
+
1
dep[y]>dep[x]+1
dep[y]>dep[x]+1的
y
y
y问
y
y
y到三个儿子中的两个的距离,由于我们知道这三个距离分别是
d
,
d
+
2
,
d
+
2
d,d+2,d+2
d,d+2,d+2所以知道两个相当于是知道第三个,因此可以直接找到它属于哪一个子树、它到根的距离。
一开始
n
n
n次询问,考虑前一部分的点,找
s
z
sz
sz和
d
i
s
dis
dis最多要
2
2
2次,后一部分的点问两个儿子最多要
2
2
2次,因此只需要小于
3
n
3n
3n的操作数即可完成询问。