美文网首页线段树
支持区间修改和区间查询的线段树

支持区间修改和区间查询的线段树

作者: 学无止境1980 | 来源:发表于2019-08-04 11:04 被阅读0次

    这种线段树支持区间修改和区间查询,区间修改的操作通过懒惰标记(lazy tag)实现。

    一道支持区间修改和区间查询的线段树的模板题:Luogu P3372 【模板】线段树 1。下面附上AC代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAXN=400010;
    struct Node{
        int l,r,ls,rs;
        long long c,s;
    }T[MAXN];
    int cnt=0,x[MAXN];
    int build(int l,int r){
        int t=cnt++;
        T[t]=(Node){l,r,-1,-1,0ll,0ll};
        if(l<r){
            int mid=(l+r)>>1;
            T[t].ls=build(l,mid);
            T[t].rs=build(mid+1,r);
            T[t].s=T[T[t].ls].s+T[T[t].rs].s;
        }
        else T[t].s=x[l];
        return t;
    }
    void pushdown(int v){
        if(T[v].c){
            if(T[v].l<T[v].r){
                T[T[v].ls].c+=T[v].c;
                T[T[v].ls].s+=(T[T[v].ls].r-T[T[v].ls].l+1)*T[v].c;
                T[T[v].rs].c+=T[v].c;
                T[T[v].rs].s+=(T[T[v].rs].r-T[T[v].rs].l+1)*T[v].c;
            }
            T[v].c=0;
        }
    }
    void change(int v,int l,int r,int c){
        pushdown(v);
        if(l<=T[v].l && T[v].r<=r){
            T[v].c+=c;
            T[v].s+=(T[v].r-T[v].l+1)*c;
            return;
        }
        if(l>T[v].r || r<T[v].l) return;
        change(T[v].ls,l,r,c);
        change(T[v].rs,l,r,c);
        T[v].s=T[T[v].ls].s+T[T[v].rs].s;
    }
    long long query(int v,int l,int r){
        if(l<=T[v].l && T[v].r<=r) return T[v].s;
        if(l>T[v].r || T[v].l>r) return 0;
        pushdown(v);
        return query(T[v].ls,l,r)+query(T[v].rs,l,r);
    }
    int main(){
        int N, M;
        scanf("%d%d",&N, &M);
        for(int i=0;i<N;i++) scanf("%d",&x[i]);
        int root=build(0,N-1);
        while(M--){
            int t; scanf("%d",&t);
            if(t==1){
                int l,r,c; 
                scanf("%d%d%d",&l,&r,&c);
                change(root,l-1,r-1,c);
            }
            else{
                int l,r; scanf("%d%d",&l,&r);
                printf("%lld\n",query(root,l-1,r-1));
            }
        }
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:支持区间修改和区间查询的线段树

        本文链接:https://www.haomeiwen.com/subject/webedctx.html