[线段树] (e) Luogu3372 (模版题)
如在阅读本文时遇到不懂的部分,请在评论区询问,或跳转 线段树总介绍
此题过水不予讲解
代码(不知道为什么当时long long用不了就用了unsigned long)
/*luogu3372*/ /*模版*/ #include<iostream> #include<cstdio> using namespace std; typedef unsigned long int LL; const LL N=1e6+5; LL n,m,a[N],v[N<<2],tag[N<<2]; void build(LL rt,LL l,LL r){ if(l==r){v[rt]=a[l];return;} LL mid=l+r>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); v[rt]=v[rt<<1]+v[rt<<1|1]; } void pushdown(LL rt,LL l,LL r){ tag[rt<<1]+=tag[rt],tag[rt<<1|1]+=tag[rt]; LL mid=l+r>>1; v[rt<<1]+=tag[rt]*(mid-l+1); v[rt<<1|1]+=tag[rt]*(r-mid); tag[rt]=0; } void update(LL rt,LL l,LL r,LL x,LL y,LL k){ if(l>=x&&r<=y){tag[rt]+=k;v[rt]+=(r-l+1)*k;return;} if(tag[rt])pushdown(rt,l,r); LL mid=l+r>>1; if(x<=mid)update(rt<<1,l,mid,x,y,k); if(y>mid)update(rt<<1|1,mid+1,r,x,y,k); v[rt]=v[rt<<1]+v[rt<<1|1]; } LL query(LL rt,LL l,LL r,LL x,LL y){ if(x<=l&&y>=r)return v[rt]; if(tag[rt])pushdown(rt,l,r); LL mid=l+r>>1,res=0; if(x<=mid)res+=query(rt<<1,l,mid,x,y); if(y>mid)res+=query(rt<<1|1,mid+1,r,x,y); return res; } int main(){ scanf("%ld%ld",&n,&m); for(LL i=1;i<=n;++i)scanf("%ld",&a[i]); build(1,1,n); LL tp,x,y,z; while(m--){ scanf("%ld%ld%ld",&tp,&x,&y); if(tp==1){ scanf("%dl",&z); update(1,1,n,x,y,z); }else printf("%ld\n",query(1,1,n,x,y)); } return 0; }
End