码迷,mamicode.com
首页 > 其他好文 > 详细

P6071 - 『MdOI R1』Treequery 题解

时间:2021-03-05 13:21:24      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:叠加   相减   运算   简单   维护   根据   深度   次数   两种   

从这题学到许多,故写题解以记之。(orz ix35)


分个类:

  • \(l\sim r\) 全是 \(p\) 的后代,则答案就是 \(p\) 到它们的 LCA 的距离;
  • 若既有后代又有祖先,答案显然是 \(0\)
  • 只有祖先的话,还要分两种情况:如果它们到 \(p\) 的路径的交是不是一条直链的话(即 LCA 不是 \(p\) 的祖先),那么答案就是 LCA 到 \(p\) 的距离;否则就是 \(l\sim r\) 分别与 \(p\) 的 LCA 中最深的,下面重点讨论。

对上面情况的判断,就是数 \(p\) 子树内有多少 \([l,r]\) 内的节点。把子树问题转化成 dfn 就是个二维数点,由于是静态的,可以直接主席树做到 1log。

先抛个一开始假想的时候的结论:一堆点(一个区间)的 LCA 显然可以直接线段树维护,而可以证明,若按照 dfn 排序,则答案是两端的 LCA。很可以感性理解,但也容易证明,结合虚树理论想一下就出来了。但这对做这题并没有用,直接维护区间反而好写。注意到 LCA 也是可叠加的,于是也可以用 ST 表做到 \(\mathrm O(1)\) 查询,预处理由于次数是线对,所以需要用 \(\mathrm O(n\log n)-\mathrm O(1)\) 的欧拉序 + ST 表求 LCA。

\(l\sim r\) 按 dfn / 欧拉序排序后,将 \(p\) 也插进去,那么根据欧拉序 + ST 表求 LCA 法可知,\(p\) 与后继的 LCA 是与更后面节点的 LCA 的后代(越往后面取,LCA 深度越小);左边类似。于是我们只需要求 \(p\) 的前驱与后继。

自然想到 2log 的树套树。考虑其本质,前驱后继其实是个变了个形的二维数点,范围是第一维是对应区间,第二维是值域上的前缀 / 后缀,运算从加法变成了求 max / min。但是这玩意没有可减性,所以树套树也是只能区间查询,而非前缀查询然后相减。幸运的是,第二维(值域维)是前缀 / 后缀,可以正反两遍对该维主席树,然后对第一维区间查询。

但是这样太麻烦了(大雾)。前驱后继这玩意有更优秀的性质:每个点的点权就是第二维坐标。所以如果我们把第一维压扁的话,那么就不是一个复杂的 RMQ,而是直接找有值的地方,可以用类似树上二分的更简单的写法(但是区间查询的写法更为直观?)。而「有值」这玩意(即 cnt)是可减的,于是我们可以直接将左右两端两棵树相减,然后在上面二分。

code(写老长了)

P6071 - 『MdOI R1』Treequery 题解

标签:叠加   相减   运算   简单   维护   根据   深度   次数   两种   

原文地址:https://www.cnblogs.com/ycx-akioi/p/solution-p6071.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!