[洛谷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; }