题目大意:
你有N个整数,A1,A2,.,An。你需要处理两种操作。一种操作是在给定的区间内向每个数字加上一个给定的数字。另一种是求给定区间内的数字之和。
题解:
线段树的基本操作。
lazy标记。
附上代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n,q,a[100001]; long long sum[400001],tag[400001]; void pushup(int k) { sum[k]=sum[k<<1]+sum[k<<1|1]; } void build(int l,int r,int k) { if(l==r) { sum[k]=a[l]; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); pushup(k); } void lazy(int l,int r,int k,int p) { tag[k]+=p; sum[k]+=(r-l+1)*p; } void pushdown(int l,int r,int k) { int mid=(l+r)>>1; lazy(l,mid,k<<1,tag[k]); lazy(mid+1,r,k<<1|1,tag[k]); tag[k]=0; } void update(int l,int r,int x,int y,int v,int k) { if(x<=l&&y>=r) { sum[k]+=(r-l+1)*v; tag[k]+=v; return; } pushdown(l,r,k); int mid=(l+r)>>1; if(mid>=x) update(l,mid,x,y,v,k<<1); if(mid<y) update(mid+1,r,x,y,v,k<<1|1); pushup(k); } long long query(int l,int r,int x,int y,int k) { if(x<=l&&y>=r) return sum[k]; pushdown(l,r,k); int mid=(l+r)>>1; long long ans=0; if(mid>=x) ans+=query(l,mid,x,y,k<<1); if(mid<y) ans+=query(mid+1,r,x,y,k<<1|1); return ans; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); for(int i=1;i<=q;i++) { char k[2]; scanf("%s",k); if(k[0]=='Q') { int x,y; scanf("%d%d",&x,&y); printf("%lld ",query(1,n,x,y,1)); } else { int x,y,z; scanf("%d%d%d",&x,&y,&z); update(1,n,x,y,z,1); } } }