2022.8.5 闲话

发现一个很好玩的东西,

Problem 1

维护一个森林,要求支持:

  • 选中一个节点,求这个节点所在树的直径 .
  • 选中两棵树,连接一条能使得两棵树连接后直径最小的边 .

所有边权都为 1 .

题目来源 .

合并直接并查集,初始的直径先预处理一波 .

观察操作 2,发现一个很显然的结论,就是两棵树中的直径中点连边,连后的直径最小 . 然后观察这两棵树的最长链上的节点个数:

  • 如果两个都是奇链,合并后的中点选合并前的中点的任意一个就可以 .
  • 如果一个是奇链,一个是偶链,合并后的中点选偶链上的那个中点 .
  • 如果两个都是偶链,合并后的中点选合并前的中点的任意一个就可以 .

设连结前 A 树的直径为 \(d_a\),B 树的直径为 \(d_b\)。很显然,合并后的直径为 \(d_c = \left\lceil\dfrac{d_a + 1}{2}\right\rceil + \left\lceil\dfrac{d_b + 1}{2}\right\rceil\) .

然后在并查集上进行合并和信息向上传递即可 .


以下所有边权都是正数 .

Problem 2

维护一个森林,要求支持:

  • 选中一个节点,求这个节点所在树的直径 .
  • 选中两棵树,连接一条能使得两棵树连接后直径最长的边 .

看起来和 Problem 1 十分相似,但实际上这题简单很多(口胡)

结论:两棵树 \(\mathcal T_1,\mathcal T_2\) 的直径分别是 \(u\leftrightarrow v\)\(x\leftrightarrow y\),则用一条边将两棵树连接后,新直径的端点必然在 \(\{u,v,x,y\}\) 中 .

关于加边动态直径见 Problem 4,这里先放着(伏笔)


Problem 3

给你一棵树,要求支持:

  • 查询子树直径长度 .
  • 删掉一个子树 .

注意到子树操作,于是考虑 DFS 序维护 .

当我们删除一个在 DFS 序上连续的区间时,考虑把两个区间进行合并,这样就是 Problem 2
的结论了 .

合并只需快速计算两点间距离,等价于快速 LCA .

这样最快能做到 \(O(n)\) 预处理 \(O(1)\) 操作 .

当然作为一个正常人谁写标准 RMQ 啊,但是也别傻乎乎地写倍增,朴素 RMQ 是单次询问 \(O(1)\),预处理 \(O(n\log n)\) 的,不知道比倍增高到哪里去了 .


Problem 4

给你一个森林,要求支持:

  • 加一条边,保证加完还是树 .
  • 求全局直径 .

注意到加边,于是考虑 LCT .

Problem 2 的性质,只需维护直径端点 .

加边就 LCT 暴力干即可,\(O(n\log n)\) .

自带 6 倍常数,还得加上 LCT 巨大常数,刺激!

posted @ 2022-08-05 20:35  Jijidawang  阅读(58)  评论(1编辑  收藏  举报
😅​