线段树 -- 区间修改 【下放懒人标记】

//分为区间覆盖,区间加或减. 这里只写一种区间覆盖(其他的照着改一下就可以了). 如果都有那就要是双标记, 下一篇讲 .

模板题
板子:

const int maxn = 1e5+5;
int a[maxn];
struct Tree {
    int tl, tr; ll val, lazy;
    void fun(ll tmp) {      //如果是加值是所有的 = 都用 +=. 下次不要被坑啦!
        lazy = tmp;
        val = (tr - tl + 1) * tmp;
    }
} tre[maxn<<2];
void pushup(int id) {
    tre[id].val = tre[id<<1].val + tre[id<<1|1].val;
}
void pushdown(int id) {
    if(tre[id].lazy) {
        tre[id<<1].fun(tre[id].lazy);
        tre[id<<1|1].fun(tre[id].lazy);
        tre[id].lazy = 0;
    }
}
void build(int id,int l,int r) {
    tre[id].tl = l; tre[id].tr = r; tre[id].lazy = 0;
    if(l == r) {
        tre[id].val = a[l];
        return ;
    }
    int mid = (l+r) >> 1;
    build(id<<1, l, mid);
    build(id<<1|1, mid+1, r);
    pushup(id);
}
void update(int id, int ul, int ur, int val) {
    int l = tre[id].tl, r = tre[id].tr;
    if(ul <= l && r <= ur) {
        tre[id].fun(val);
        return ;
    }
    pushdown(id);
    int mid = (l+r) >> 1;
    if(ul <= mid) update(id<<1, ul, ur, val);
    if(ur > mid) update(id<<1|1, ul, ur, val);
    pushup(id);
}
ll query(int id, int ql, int qr) {
    int l = tre[id].tl , r = tre[id].tr;
    if(ql <= l && r <= qr) {
        return tre[id].val;
    }
    pushdown(id);
    int mid = (l+r) >> 1 ;
    if(qr <= mid) return query(id<<1, ql, qr);
    else if(ql > mid) return query(id<<1|1, ql, qr);
    else return query(id<<1, ql, mid) + query(id<<1|1, mid+1, qr);
    // 还是这样写线段树好一点.
}

void solve() {
    int n;
    scanf("%d",&n);
    for(int i = 1 ; i <= n ; i ++) {
        scanf("%d", &a[i]);
    }
    build(1, 1, n);
    int q; scanf("%d",&q);
    while(q--){
        int op, l, r, w;
        scanf("%d%", &op);
        if(op == 0){
            scanf("%d%d", &l, &r);
            printf("%lld\n", query(1, l, r));
        }
        else{
            scanf("%d%d%d", &l, &r, &w);
            update(1, l, r, w);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值