https://vjudge.net/problem/POJ-3468
线段树区间更新,记录模板
#include<stdio.h> #include<iostream> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int maxa=100005; ll c,s[maxa],lazy[maxa*4],sum[maxa*4]; int n,q,a,b; char ch; void build(int l,int r,int rt) { int mid=(l+r)/2; if(l==r) { sum[rt]=s[mid]; return ; } build(l,mid,rt*2); build(mid+1,r,rt*2+1); sum[rt]=sum[rt*2]+sum[rt*2+1]; } void pushdown(int rt,int len) ///rt为sum下标,后者是该区间的数组元素个数 { if(lazy[rt]) { lazy[rt*2] += lazy[rt]; lazy[rt*2+1]+= lazy[rt]; ///父节点有标记,把标记给两个儿子 sum[rt*2] += (ll)(len-len/2)*lazy[rt]; sum[rt*2+1] += (ll)(len/2)*lazy[rt]; lazy[rt]=0; ///消除标记,底层的没有办法消除, } } void update(int l,int r,int rt,ll c) { if(a<=l && r<=b) ///如果区间在修改范围里,标记一下rt { lazy[rt]+=c; ///如果没有消除,需要叠加,如果消除过,也是和0叠加 sum[rt]+= (ll)c*(r-l+1);///直接加到大区间段,不要细分下去,节省时间 return ; } pushdown(rt,r-l+1);///搞不好下面就需要用到标记区间的左右子树数据,所以都要先 int mid = (l+r)/2; if(b<=mid) update(l,mid,rt*2,c); else if(a>mid) update(mid+1,r,rt*2+1,c); else { update(l,mid,rt*2,c); update(mid+1,r,rt*2+1,c); } sum[rt]=sum[rt*2]+sum[rt*2+1]; } ll query(int l,int r,int rt) { if( a<=l && r<=b ) return sum[rt]; pushdown(rt,r-l+1); int mid = (l+r)/2; if(b<=mid) return query(l,mid,rt*2); else if(a>mid) return query(mid+1,r,rt*2+1); else return query(l,mid,rt*2)+query(mid+1,r,rt*2+1); } int main() { memset(lazy,0,sizeof(lazy)); memset(sum,0,sizeof(sum)); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%lld",&s[i]); build(1,n,1); while(q--) { getchar();///吸收回车键 scanf("%c",&ch); if(ch=='Q') { scanf("%d%d",&a,&b); printf("%lld\n",query(1,n,1)); } else { scanf("%d%d%lld",&a,&b,&c); update(1,n,1,c); } } return 0; }