[洛谷P3372]【模板】线段树 1

题目大意:区间修改与求和。

线段树(线断术)模板题。

C Code:

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define LL long long
LL d[500000*3+5],n,m,a[500000+1],le,rr,add,u[500000*3+5];
void make(LL l,LL r,LL o){
    if(l==r){
        d[o]=a[l];
        return;
    }
    LL m=(l+r)>>1;
    make(l,m,o<<1);
    make(m+1,r,o<<1|1);
    d[o]=d[o<<1]+d[o<<1|1];
}
void pushdown(LL l,LL r,LL o){
    u[o<<1]+=u[o];
    u[o<<1|1]+=u[o];
    d[o<<1]+=u[o]*(r-l+2>>1);
    d[o<<1|1]+=u[o]*(r-l+1>>1);
    u[o]=0;
}
void plus(LL l,LL r,LL o){
    if(le<=l&&r<=rr){
        u[o]+=add;
        d[o]+=add*(r-l+1);
        return;
    }
    pushdown(l,r,o);
    int m=(l+r)>>1;
    if(le<=m)plus(l,m,o<<1);
    if(m<rr)plus(m+1,r,o<<1|1);
    d[o]=d[o<<1]+d[o<<1|1];
}
LL query(LL l,LL r,LL o){
    if(le<=l&&r<=rr)return d[o];
    pushdown(l,r,o);
    LL m=(l+r)>>1;
    LL t=0;
    if(le<=m)t+=query(l,m,o<<1);
    if(m<rr)t+=query(m+1,r,o<<1|1);
    return t;
}
int main(){
	scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    make(1,n,1);
    memset(u,0,sizeof(u));
    while(m--){
        LL x;
        scanf("%lld",&x);
        if(x==1){
        	scanf("%lld%lld%lld",&le,&rr,&add);
            plus(1,n,1);
        }else{
        	scanf("%lld%lld",&le,&rr);
            printf("%lld\n",query(1,n,1));
        }
    }
    return 0;
}

 

posted @ 2017-07-12 10:50  Mrsrz  阅读(142)  评论(0编辑  收藏  举报