题目大意:区间修改与求和。
线段树(线断术)模板题。
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
",query(1,n,1));
}
}
return 0;
}