动态开点线段树——节约资源,你值得拥有 NOIP2017 列队

简介:

发现,有的时候,线段树需要维护的区间很大很大,但是实际用到的节点很少很少。

那么,我们干脆就不要开这么多的节点,用到的时候再向内存要。

也就是说,我们建立了一棵残疾的线段树,缺少很多枝叶,但是绝对够用了。

画个图大概理解一下(虽然也不太对)

实心边框的点都是我们申请内存给的,虚的点是没用的。就算申请也不用,实在是浪费资源。

所以,

我们开局只有一个根,装备叶子全靠给。

例如我们要建立一个权值线段树,但是在线操作不让你离散化,值域又是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/次

例题:(里面也有本篇的部分讲解)

NOIP2017 列队

猜你喜欢

转载自www.cnblogs.com/Miracevin/p/9582486.html