线段树的区间更新+懒惰标记

 这一部分感觉是最难的一部分了。

想要更新区间的值,可以通过一个for循环进行单点更新。。但是这样貌似比普通的遍历还慢。

所以,聪明的人们想到了一个好办法解决线段树不能解决区间更新的问题。通过一个懒惰标记来对已经更新的区间进行标记,然后计算出值,然后直接返回,不在更新子节点的值了。

当进行多次更新的时候,这时候就可以通过下推标记进行更新子节点。

代码如下:

下推懒惰标记:

//下推懒惰标记
int lazy[maxn<<2];
void Pushdown (int re,int ln,int rn) //ln 表示的是左子树的元素个数,rn表示的是右子树的元素个数
{
    //如果有懒惰标记
    if(lazy[re])
    {
        lazy[re<<1]+=lazy[re];
        lazy[re<<1|1]+=lazy[re];
        //求出两个子节点的值
        tree[re<<1]+=lazy[re]*ln;
        tree[re<<1|1]+=lazy[re]*rn;
        //因为标记已经下传了,所以重新置0
        lazy[re]=0;
    }
}

区间更新:

//区间更新
void quee (int left,int right,int l,int r,int re,int data)// [left,right]表示要查询的区间,data表示区间更新的数值
{
    if(l>=left&&r<=right)
    {
        //加上懒惰标记,并求出区间更新后的值
        lazy[re]+=data;
        tree[re]=data*(r-l+1);
        return ;
    }
    int mid=(l+r)>>1;
    //是否需要下推标记
    Pushdown (re,mid-l+1,r-mid);
    if(mid>=left)
        quee (left,right,l,mid,re<<1,data);
    if(mid<right)
        quee (left,right,mid+1,r,re<<1|1,data);
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/81607304