bzoj 2870

20 pts

其中有 \(20\%\) 的数据树退化成一条链。

考虑树为链的做法。对于一个点,我们钦定它是当前点权最小的点,那么此时为了让点权乘链长最大,我们考虑尽可能地往左边和右边扩展,也就是此时查询左边第一个小于它点权的点的右边,右边第一个小于它点权的点的左边,这个直接使用二分即可做到 \(O(\log n)\)。因此我们直接枚举该点并应用以上扩展即可做到 \(O(n\log n)\)

100 pts

Sol 1 并查集维护树的直径

考虑不为链怎么做?依旧考虑钦定一个点,如果该点为最小值,相当于比它小的点都不可以加入这条链,相当于删掉了这个点。那么当前的所有存在的点都是大于等于它的点,这个时候连通块的直径就是答案。单次求直径是 \(O(n)\) 的,如果暴力那么就是 \(O(n^2)\) 的。

然而,我们可以继承一些信息,如果我们从大到小枚举点,那么原先保留的点,之后依然存在,同时,我们还会加入一些点。

题目现在变成了这样:

你需要维护一个树状连通块,每次加入一个点,并查询该点所在连通块的直径。

这显然是 Colorful tree 的一个结论,就是如果两个连通块 AB 合并,且 A 连通块的任意直径为 \((x_A,y_A)\),同样的 B,那么合并后的连通块的直径的两个点只有可能在 \(\{x_A,y_A,x_B,y_B\}\) 里面选取。

证明:若 \(x,y \in S_{1}\),则它们的距离一定不会大于 \(x_{A},y_{A}\) 的距离。对于 \(S_2\),也是同理。现在考虑 \(x \in S_{A},y\in S_{B}\)。考虑反证调整法,若 \(x \in S_{A},y \in S_{B},x \ne x_{A},y_{A}\)。则 \(z\) 一定可以通过向 \(x_A\) 或者 \(y_A\) 移动来使得与 \(y\) 的距离增大。因为 \(x\) 要么是直径上的点,要么是延申的枝条上的点。

因此,我们只需要维护每个连通块的直径,直接合并即可。瓶颈在于查询两点的距离,使用平凡算法做到 \(O(\log n)\),使用长链剖分做到 \(O(1)\)(此时瓶颈是并查集)。

总复杂度为 \(O(n\log n)\)\(O(n \alpha(n))\)

posted @ 2026-04-15 22:07  PM_pro  阅读(8)  评论(0)    收藏  举报