简介:
发现,有的时候,线段树需要维护的区间很大很大,但是实际用到的节点很少很少。
那么,我们干脆就不要开这么多的节点,用到的时候再向内存要。
也就是说,我们建立了一棵残疾的线段树,缺少很多枝叶,但是绝对够用了。
画个图大概理解一下(虽然也不太对)
实心边框的点都是我们申请内存给的,虚的点是没用的。就算申请也不用,实在是浪费资源。
所以,
我们开局只有一个根,装备叶子全靠给。
例如我们要建立一个权值线段树,但是在线操作不让你离散化,值域又是inf级别的,
像这样,即使这个区间的范围很大,但是如果询问q比较少的话,我们只需要qloginf个节点,就可以办到。
具体代码实现:
不同的操作,但是大同小异。
还是类似于一般线段树的。
框架:
function(int &x,int l,int r,int blablabla){
if(!x){
//建新节点,并处理信息
if(l==r) //叶子节点由于是真正要用的节点(对于单点),往往还要特殊记录信息
}
if(blablabla) return ???//判断是否能返回等等
(int ret) // 如果需要返回时停留更新信息,就弄一个ret
if(blablabla) return (t[x].ls,l,mid,blablabla)
if(blablabla) return (t[x].rs,mid+1,r,blablabla);
(pushup(x)) //回溯后更新
}
发现和主席树有点像,但是省空间的思想还是有些不同的。
主席树是:多棵线段树,利用相邻之间有很大部分是相同的。可以在之前线段树基础上建立线段树。
特点:许多线段树共用儿子节点
动态开点线段树:一棵线段树,利用实际用到的点不多,少开了很多节点。
特点:区间范围很大(通常不能直接开下)
共同点:(都是线段树)
都通过新加入的节点有限,进行的空间优化。使得时间空间复杂度都是logn/次
例题:(里面也有本篇的部分讲解)