1. 程式人生 > >BZOJ3212 Pku3468 A Simple Problem with Integers(線段樹區間求和、區間加模板)

BZOJ3212 Pku3468 A Simple Problem with Integers(線段樹區間求和、區間加模板)

題目大意:

你有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\n",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); } } }