线段树lazy

来看一道线段树模板题,

题目在此

看完题目就知道是一个线段树的模板题,再看下数据范围,1e5,就知道如果直接暴力修改的话那么肯定超时,

所以用了lazy标记,先标记再修改,初始化的时候先把lazy置为0,如果发现区间有修改的情况,那么先把这个结点更新一下,

再把这个结点lazy标记一下,如果查询lazy不为0的结点的话那么就把lazy更新到子节点上,这样就不用每次都更新所有结点了,具体看code。

 蒟蒻的代码(水过):

#include<iostream>
using namespace std;
typedef long long LL;
const int MAX=1e5+10;

struct node {
    int l;
    int r;
    LL val;
    LL lazy;
}nodes[4*MAX];
int inv;

void push(int x){
    nodes[x].val=nodes[x<<1].val+nodes[x<<1|1].val;
}

void pushdown(int x){
    if(nodes[x].lazy!=0){
        int mid=nodes[x].l+nodes[x].r>>1;
        nodes[x<<1].lazy+=nodes[x].lazy;
        nodes[x<<1|1].lazy+=nodes[x].lazy;
        nodes[x<<1].val+=(mid-nodes[x].l+1)*nodes[x].lazy;
        nodes[x<<1|1].val+=(nodes[x].r-mid)*nodes[x].lazy;
        nodes[x].lazy=0;
    }
}

void build(int root,int ll,int rr){
    nodes[root].lazy=0;
    nodes[root].l=ll;
    nodes[root].r=rr;
    if(ll==rr){
        cin>>inv;
        nodes[root].val=inv;
    }
    if(ll>=rr)return ;
    int mid=(ll+rr)>>1;
    build((root<<1),ll,mid);
    build((root<<1)|1,mid+1,rr);
    push(root);
}

void add(int root,int ll, int rr,int val){
    if(ll>nodes[root].r||rr<nodes[root].l)return ;
    if(ll<=nodes[root].l&&rr>=nodes[root].r){
        nodes[root].lazy+=val;
        nodes[root].val+=(nodes[root].r-nodes[root].l+1)*val;
        return;
    }
    pushdown(root);
    int mid=(nodes[root].l+nodes[root].r)>>1;
    if(ll<=mid)add(root<<1,ll,rr,val);
    if(rr>mid)add(root<<1|1,ll,rr,val);
    push(root);
}

LL query(int root,int ll,int rr){
    if(rr<nodes[root].l||ll>nodes[root].r)return 0;
    
    if(ll<=nodes[root].l&&rr>=nodes[root].r){
        return nodes[root].val;
    }
    pushdown(root);
    int mid=(nodes[root].l+nodes[root].r)>>1;
    LL leftval=0,rightval=0;
    if(ll<=mid)leftval=query(root<<1,ll,rr);
    if(rr>mid)rightval=query(root<<1|1,ll,rr);
    return leftval+rightval;
}

int main(){
    int n,m;
    cin>>n>>m;
    build(1,1,n);
    while(m--){
        char c;
        cin>>c;
        if(c=='Q'){
            int l,r;
            cin>>l>>r;
            cout<<query(1,l,r)<<endl;
        }
        else {
            int l,r,v;
            cin>>l>>r>>v;
            add(1,l,r,v);
        }
    }
    return 0;
}

 总结:以后还是找个大佬的板子比较好,自己的板子太水了QAQ。

posted @ 2020-03-21 15:04  kstranger  阅读(171)  评论(0)    收藏  举报