注意:本文全程口胡。暂时没有代码。
猫树,出自immortalCO的博客,是“一种高效处理无修改区间或树上询问的数据结构”。
lxl说他自己反对用猫树这个名字,并且认为这个名字就像ODT一样奇怪,可能叫“二区间合并”更好一些
首先我们要明确猫树能干什么。
就如immortalCO的博客的标题所写的,猫树能够处理区间无修改询问(树上的一遍搞个dfs序/树链剖分就成区间问题了)。
当然这个询问需要满足一些简单的性质,比如有结合律,支持快速合并。像最大值,区间和,\(\gcd\),最大子段和这样的都可以维护。
猫树的优势在于询问的时候可以做到 \(O(1)\),比线段树少一个 \(\log\)。
但是,猫树的劣势也很明显,就是做不了修改操作。
接下来我们给出猫树的思想及其算法实现。
猫树的思想在于利用分治做好预处理,以获得较低的询问复杂度。可以类比 ST 表,长链剖分做 LA 问题。
具体操作如下:我们取当前区间的中点,分别记录从中点出发,向左向右的“中缀和”。然后递归地对左右区间进行相似操作。
方便起见,称这些点为记录点。
举个例子理解一下:现在我们有区间 \(1\ 4\ 2\ 3\),现在要维护和。
取 \(4\) 为中点向左向右统计,得到的就是 \(5\ 4\ 6\ 9\)。
时空复杂度:因为递归 \(\log n\) 层,得时空复杂度都为 \(O(n\log n)\)。
接下来是查询。我们的思想是,找到一个查询区间中间的记录点(很明显是存在的),然后利用已知的中缀和把左端点到中间,中间到右端点两个区间的答案合并起来就行了。这也就是为什么这个算法也被叫做二区间合并。
具体操作的时候,为了做到 \(O(1)\),我们需要一点位运算的小技巧。
我们发现,如果数组的下标从 \(0\) 开始,那么两个端点的二进制最长前缀长度就是其所在区间的深度。根据深度和左右端点我们就能 \(O(1)\) 确定记录点了qwq
(二进制lcp求法:\(x>>\log_2(x \text{ xor } y)\))