题解:CF1987G2 Spinning Round (Hard Version)
upd on 2024.10.6: 修了一张挂掉的图片。
Fun fact:本题被用作了一场 NOIP 模拟赛的 T4。
本文一定程度上参考了 @qiuzx 的 题解。
一些初步的想法是:最终连出来的一定是一棵树;如果除了最大值之外还有其他点只能连自己,则无解。
考虑建出排列对应的大根笛卡尔树。
对于一种不连向自己的连边方案,向左连边就等价于在笛卡尔树上往上跳,直到第一次以右儿子的身份跳上去;向右连边则对应第一次以左儿子的身份跳上去。
考虑在笛卡尔树上 dfs,顺带维护这棵新连出的树的直径。
在 dfs 前,我们可以先预处理出只能向右/向左连边的点,稍后特判即可。
类比树的直径的树形 DP 做法,我们尝试在 LCA 处统计贡献。
记
特别地,对于
假设我们现在在点
- 路径不要求含
x :
注意到如果向左连边并且跳出了左子树,那么一定也跳出了
x 所在子树。其余情况同理。
- 路径要求包含
x ,且x 向左连边:
注意到:
这种情况必然不会对
f_{x,1} 产生贡献;第一个柿子表示从左/右子树跳到了
x ,再用一步跳出去;第二个柿子表示,如果存在一左一右两条跳出
x 子树的路径,由于x 已经向左跳出,且左子树向右跳只可能跳到x ,故一定是右子树提供了这条向右跳出的路径。
- 路径要求包含
x ,且x 向右连边:
类似 2,不再赘述。
最后来统计答案,记路径两端点的 LCA 为点
- 两端点分属
x 的两个子树:
- 两端点来自
x 同一子树内的两条不同路径:
这种情况就不方便在 LCA 处统计了,因为两条边有可能是从子树内很深的点远道而来;我们转而考虑汇合前的最后一次跳跃。
枚举其中一个端点最后一次连边的方向,不妨设在点
上式的含义是,要么左子树向左连边,在
y 上方与x 向左连的边汇合,同时右子树向左连向y ;要么左子树连出一左一右两条边,其中向左的那条边与y 连的边汇合,向右的那条连向y 。
综上,我们在