【题解】CF1866K 树的直径 李超线段树 凸包

简单题。

新树的直径一定经过了翻倍的点或者为原树的直径。

先使用换根求出每个点子树内以及子树外最远点的距离,然后接下来对于一个询问的点,我们关心每个儿子内及这个子树的补树内最远的点距离加上这条边翻倍后的长度的最大值和次大值。

假设某个子树内最远点为 $f_v$,到该子树的边的长度为 $w_v$,那么我们相当于要对于某个给出的 $k$,求出 $k w_v + f_v$ 的最大值及次大值。

求最大值是简单的,使用李超线段树或者凸包维护即可。

考虑如何求次大值:(与最大值不同的次大值)

凸包求法:

维护所有 $f_i(x)=k_ix+b_i$ 构成的下凸包,查询最大值对应的直线。

次大值一定被这两种情况包含:

  • 不在这个下凸包上的直线上:用这些直线再建一个凸包查询即可。
  • 凸包上的前一条或者后一条直线。

一定不可能被凸包上的其它直线包含,因为这些值以及在对应位置是低于前一条或后一条直线的。

李超树求法:

查询最大值及其位置。

查询去除这个最大值后的最大值。

扣掉某个元素的常见做法是维护后缀和前缀信息:维护每个点的前 $i$ 条直线,后 $i$ 条直线的李超树 $pre_i,suf_i$,然后在 $pre_{mx-1},suf_{mx+1}$ 里面查就行了。实现可以离线或者使用可持久化李超树。

代码

posted @ 2023-09-04 15:08  寂静的海底  阅读(18)  评论(0编辑  收藏  举报  来源