【复习】线段树(3)区间修改与lazy标记——标记永久化

对线段树的lazy标记,分别有“标记下传”与“标记永久化”两种操作思路,上一篇写了“标记下传”,这一篇写“标记永久化”。
“标记永久化”与“标记下传”相比,区别在于“标记永久化”在更新节点时,就一次性将所有需要更改的节点的标记修改完成,查询时无需对标记进行修改。
以查询信息为区间和为例,用“标记永久化”思路进行解题。
存储信息用的数组同样需要两个,sum[]记录区间和,add[]记录区间增加标记。
其中,当修改区间完全包含当前区间时,仅修改add[]值,修改值为单个节点改变量若不完全包含,则仅对sum[]值进行修改,修改值为单个节点改变量×(修改区间与当前区间重合长度),然后继续对该区间的子区间重复上述操作。
按上述思路进行区间修改后,查询思路如下:
当查询区间完全包含当前区间时,直接返回该区间的sum值+该区间add值*该区间长度。
否则,该区间返回值为该区间add值×(查询区间与当前区间重合长度)+左子区间返回值+右子区间返回值

对于两区间重合部分长度,计算方法如下:
区间a[l,r],区间b[x,y]
len=min(y,r)-max(x,l)+1

代码:

void Updata(int o,int l,int r,int x,int y,int k)        //区间修改
{
 if(x<=l&&y>=r)
 {
  add[o]+=k;
  return;
 }
 sum[o]+=k*(min(y,r)-max(x,l)+1);
 int m=(l+r)>>1;
 if(x<=m)Updata(o*2,l,m,x,y,k);
 if(y>m)Updata(o*2+1,m+1,r,x,y,k);
}

int Query(int o,int l,int r,int x,int y)                //区间查询
{
 if(x<=l&&y>=r)return sum[o]+add[o]*(r-l+1);
 int m=(l+r)>>1;
 int res=add[o]*(min(y,r)-max(x,l)+1);
 if(x<=m)res+=Query(o*2,l,m,x,y);
 if(y>m)res+=Query(o*2+1,m+1,r,x,y);
 return res;
}

区间永久化优势在于特定情况下,操作比标记下传更加方便。其时间复杂度是稳定的,可能比标记下传略慢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值