猫树 学习笔记
参考资料
概述
猫树,一种支持快速查询区间信息的数据结构,可以维护各种满足结合律的信息,如区间和,区间最值,平均数等
可以在 $O(nlogn)$ 的预处理下 $O(1)$ 查询信息。在很多时候可以代替 ST表 或线段树等数据结构(但修改比较麻烦相当于重建
适用于一些不需要支持修改操作,且询问较多的题目。
实现
预处理:
我们把区间长度开到 $2^i$。为什么后面讲(
然后对于整个区间取 $mid$ 然后对于 $mid~1$ 倒序维护,对于 $mid+1~len(2^i)$ 进行正序遍历。时间复杂度 $O(n)$。
然后对左右区间继续分,继续处理。
查询:
我们考虑对于区间 $[l,r]$,我们考虑如果 $[l,r]$ 不能同时被一个节点分成两段(不一定平分),
那么他们一定在一个节点左儿子或右儿子包含的区间内,向下迭代即可。
如果被分成两段,那么我们直接查询信息即可。
因为在这一层 $l$~$mid$ 的区间的信息都维护在了 $f_l$ 上,$mid+1$~$r$ 的区间的信息都维护在了 $f_r$ 上,所以直接合并即可。
很容易发现这个点就是两个节点在这棵猫树上的 $LCA$!
那么现在的问题就转化为求两点 $LCA$ 所在层。(因为我们将同一层的信息维护到同一维数组里)
但我们查询效率是 $O(1)$ 的,所以我们考虑从树的结构下功夫。
我们把数组开到了$2^i$ 就是为了现在!我们很容易发现在堆式结构存储的猫树上两点 $LCA$ 即为两点的 $LCP$(最长公共前缀)!(大家可以手模一下。
所以我们把两个数异或起来求 $log$ 再求原来点的 $log$,相减即为深度。
以ST表模板题为例:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 6 using namespace std; 7 8 static char buf[100000],*pa=buf,*pd=buf; 9 #define gc pa==pd&&(pd=(pa=buf)+fread(buf,1,100000,stdin),pa==pd)?EOF:*pa++ 10 inline int read() 11 { 12 register int x(0);register char c(gc); 13 while(c<'0'||c>'9')c=gc; 14 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc; 15 return x; 16 } 17 void print(int x){ 18 if(x<0) {putchar('-');x=-x;} 19 if(x>9) print(x/10); 20 putchar(x%10+'0'); 21 } 22 23 const int N=1e5+5; 24 int n,m,a[N<<1],l,r; 25 int len=1,f[N<<1][25],t[N<<1],lg[N<<2]; 26 27 void build(int node,int l,int r,int dep){ 28 if(l==r){ 29 t[r]=node; 30 return ; 31 } 32 int mid=(l+r)>>1; 33 build(node<<1,l,mid,dep+1); 34 build(node<<1|1,mid+1,r,dep+1); 35 f[mid][dep]=a[mid]; 36 for(int i=mid-1;i>=l;i--) 37 f[i][dep]=max(f[i+1][dep],a[i]); 38 f[mid+1][dep]=a[mid+1]; 39 for(int i=mid+2;i<=r;i++) 40 f[i][dep]=max(f[i-1][dep],a[i]); 41 } 42 43 int main(){ 44 n=read();m=read(); 45 for(int i=1;i<=n;i++) a[i]=read(); 46 while(len<n) len*=2; 47 build(1,1,len,1); 48 lg[0]=1;lg[1]=1; 49 for(int i=2;i<=len*2;i++) lg[i]=lg[i/2]+1; 50 while(m--){ 51 l=read(),r=read(); 52 if(l==r) print(a[r]); 53 else{ 54 int k=lg[t[r]]-lg[t[l]^t[r]]; 55 print(max(f[l][k],f[r][k])); 56 } 57 printf("\n"); 58 } 59 return 0; 60 }
需要注意的是,猫树不支持修改(会T飞
不想写ST表的时候可以写一写(
慎用!(不过考场基本用不上
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?