线段树成段增减,区间求和模板

线段树区间增减,区间求和用到了延迟标记。延迟标记是为了节省时间。比如要更新某段区间,只需更新能覆盖该段区间的最少结点的那些结点的sumv和addv数组。addv数组是延迟标记数组。只有需要更新到某个结点时,它的父亲结点需要先将延迟向子结点推,即PushDown操作。

/*
    线段树区间增减,区间求和。
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define LL long long
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
const int maxn=101000;
LL sumv[maxn*4];
LL addv[maxn*4];
void PushUP(int rt){    //向上更新

    sumv[rt]=sumv[rt*2]+sumv[rt*2+1];
}
void PusDown(int rt,int len){   //向下更新,延迟标记

    if(addv[rt]){

        addv[rt*2]+=addv[rt];
        addv[rt*2+1]+=addv[rt];
        sumv[rt*2]+=addv[rt]*(len-len/2);
        sumv[rt*2+1]+=addv[rt]*(len/2);
        addv[rt]=0;
    }
}
void build(int rt,int L,int R){

    if(L==R){

        scanf("%lld",&sumv[rt]);
        return ;
    }
    build(lson);
    build(rson);
    PushUP(rt);
}
void update(int rt,int L,int R,int l_ran,int r_ran,LL val){

    if(l_ran<=L&&R<=r_ran){

        sumv[rt]+=val*(R-L+1);
        addv[rt]+=val;
        return ;
    }
    PusDown(rt,(R-L+1));    //延迟向子结点推,并且更新子结点
    if(l_ran<=mid){

        update(lson,l_ran,r_ran,val);
    }
    if(r_ran>mid){

        update(rson,l_ran,r_ran,val);
    }
    PushUP(rt);             //回溯向上更新
}
LL query(int rt,int L,int R,int l_ran,int r_ran){

    if(l_ran<=L&&R<=r_ran){

        return sumv[rt];
    }
    PusDown(rt,(R-L+1));    //延迟向子结点推,并且更新子结点
    LL ret=0;
    if(l_ran<=mid){

        ret+=query(lson,l_ran,r_ran);
    }
    if(r_ran>mid){

        ret+=query(rson,l_ran,r_ran);
    }
    return ret;
}
int main(){

    int n,m;
    char tm[5];
    while(scanf("%d%d",&n,&m)!=EOF){
        
        //如果不清空延迟标记数组,可能对下组测试数据产生影响
        memset(addv,0,sizeof(addv));
        build(1,1,n);
        for(int i=0;i<m;i++){

            scanf("%s",tm);
            if(tm[0]=='Q'){

                int ta,tb;
                scanf("%d%d",&ta,&tb);
                printf("%lld\n", query(1,1,n,ta,tb));
            }else{

                int ta,tb;
                LL tc;
                scanf("%d%d%lld",&ta,&tb,&tc);
                update(1,1,n,ta,tb,tc);
            }
        }
    }
    return 0;
}
/*
10 5
1 2 3 4 5 6 7 8 9 10
C 3 6 3
Q 3 6
Q 1 10
Q 1 3
Q 6 8

10 5
1 2 3 4 5 6 7 8 9 10
C 3 6 3
Q 4 4

*/

  

posted @ 2015-04-04 09:28  tcgoshawk  阅读(149)  评论(0)    收藏  举报