区间修改线段树

区间修改线段树:

函数:

1、up向上传递
2、down父节点向下传递
3、modify区间修改(同时添加lazy标记)
4、query(与单点修改的差别是确认区间后要向下传递lazy标记)

代码:
///这个是区间求和的区间修改线段树
///这个是区间求和的区间修改线段树
#include
using namespace std;
const int MAX_N = 10010;
int s[4*MAX_N] = {0};///维护区间的线段树
int col[4*MAX_N] ={0};  ///向下传值的lazy标记

void up(int p)
{
    s[p] = s[2*p] + s[2*p+1];
}
///down向下传递函数也跟程序实现目的十分相关,改动也十分大
///但一般都有三个参数,编号p,衡量工具l与r
void down(int p,int l,int r)
{
    if(col[p]){      ///说明父节点存在lazy标记,则现向下传递
        int mid = (l + r) / 2;
        s[2*p] += (mid - l + 1) * col[p];
        s[2*p+1] += (r - mid) * col[p];
        col[2*p] += col[p];///传递给子节点lazy标记
        col[2*p+1] += col[p];
        col[p] = 0; ///去除父节点lazy标记
    }
}
///注意其跟单点操作的差别
void modify(int p,int l,int r,int x,int y,int v)
{
    if(x<=l&&r<=y){
        s[p] += (r - l + 1) * v;  ///修改对应区间的值
        col[p] += v; ///添加lazy标记
        return ;
    }
    down(p,l,r);   ///传本节点的lazy标记,在确认区间后就写上
    int mid = (l + r) / 2;
    if(x<=mid){
        modify(2*p,l,mid,x,y,v);
    }
    if(y>mid){
        modify(2*p+1,mid+1,r,x,y,v);
    }
    up(p);          ///不要漏了
}
///区间查询的时候记得也要传递lazy标记(up)

int query(int p,int l,int r,int x,int y)
{
    if(x<=l&&r<=y){
        return s[p];
    }
    int mid = (l + r) / 2,res = 0;
    if(x<=mid){
        res += query(2*p,l,mid,x,y);
    }
    if(y>mid)           ///y要严格大于mid
    {
        res += query(2*p,mid+1,r,x,y);
    }
    return res;
}

※维护区间最大(小)值的线段树跟单点修改线段树(公告板那题)那篇博客思想很类似,便不作多记录。

其相关的题目:

1、 习题:帕吉的肉钩
2、 习题:区间整数操作
题目较简单,便不做题解了。

而 习题:黑白石头放在下篇博客来详细记录

你可能感兴趣的:(区间修改线段树)