一听名字就很可爱的猫树qwq

Posted by Dispwnl on October 11, 2018

猫树

听说叫猫树是因为发明者$immortalCO$(猫锟)觉得猫是一种很可爱的生物qwq

一道题:

给定一个长度为$n$的序列,每次询问查询区间最大子段和

线段树随便艹啊……

复杂度是$O(n+qlogn)$(建树+查询)

这时候毒瘤出题人就说了:诶你这复杂度不优秀,要求查询不要带$log$

这时候一种可爱的数据结构就蹦出来解决ta啦,也就是猫树,复杂度是$O(nlogn+q)$($O(nlogn)$预处理,$O(1)$查询)

猫树主要用来解决区间查询某种支持结合律和快速合并的信息,并且没有修改操作

想想线段树怎么合并区间信息的

区间$[l,r]$信息是$[l,mid]$和$[mid+1,r]$的信息结合起来

考虑处理$mid$向前和向后的答案

设$l$和$r$在线段树上最后在一个区间(儿子区间中分开)的节点为$A$,显然$A$为$l,r$的$lca$

如果能快速找到$A$,就可以直接合$并[l,mid]$和$[mid+1,r]$的答案

既然是lca那么求一下树上lca就好啦

如果$i$的儿子节点为$2i$和$2i+1$,发现任意同深度的两个节点,ta们的$lca$就是ta们节点标号二进制表示的$lcp$(分开位置前面肯定是一样的祖先)

两个数$a,b$二进制$lcp$为$a»\log_{2}^{a\oplus b}$

这样就可以$O(1)$查询了qwq

上面例题的部分代码:

struct Cat_Tree{
	int sum1[21][MAX],sum2[21][MAX];
	void build(int l=1,int r=qaq,int k=1,int d=1)//qaq是最底层填满了的大小,k为编号,d为深度
	{
		if(l==r) return void(pos[l]=k);
		int sum,_sum;
		sum1[d][mid]=sum2[d][mid]=sum=_sum=a[mid],_sum=min(_sum,0);
		for(int i=mid-1;i>=l;--i)
		  sum1[d][i]=max(sum1[d][i+1],sum+=a[i]),sum2[d][i]=max(sum2[d][i+1],sum-_sum),_sum=min(_sum,sum);
		sum1[d][mid+1]=sum2[d][mid+1]=sum=_sum=a[mid+1],_sum=min(_sum,0);
		for(int i=mid+2;i<=r;++i)
		  sum1[d][i]=max(sum1[d][i-1],sum+=a[i]),sum2[d][i]=max(sum2[d][i-1],sum-_sum),_sum=min(_sum,sum);
		build(l,mid,tl,d+1),build(mid+1,r,tr,d+1);
	}
	int ask(int l,int r)
	{
		if(l==r) return a[l];
		int qwq=Log[pos[l]]-Log[pos[l]^pos[r]];
		return max(sum2[qwq][l]+sum2[qwq][r],max(sum1[qwq][l],sum1[qwq][r]));
	}
}Tree;

单调对联

恭喜您发现彩蛋!

在$2018$年的初春,一名叫做$zyf$的julao经过呕心沥血的研究,终于发明了单调对联这一划时代的数据结构

$Q:$ta能解决什么问题呢?

经过多次尝试,我们惊讶的发现,在面对任意一个没有询问的序列问题时,这种数据结构都能做到$O(1)$的优秀时间复杂度!而空间复杂度也是极小的!

但是遗憾的是,由于$zyf$先生的码风过于毒瘤,现在我们还没能做到研究透彻ta是如何处理能达到如此高效的复杂度,也许这就是凡人无法理解的智慧吧

好消息是应多方响应,$zyf$已经同意将单调对联加入百度百科,美其名曰数组

希望能早日理解$zyf$先生的智慧,想必这场$OI$界的巨大变革能使数据结构能有更大的发展!

不行我编不下去了