区间求和,区间更新。
需要覆盖区间,延迟处理。
void PushSub(int rt,int m){ if(color[rt]){ color[rt<<1]+=color[rt]; color[rt<<1|1]+= color[rt]; sum[rt<<1]+=color[rt]*(m-(m>>1)); sum[rt<<1|1]+=color[rt]*(m>>1); color[rt]=0; } }
mid= (4 +8)>>1 = 6 ;左子树的区间是[4,mid].右子树是[mid+1,8],所以这样算起来,如果区间有奇数个,左边肯定要比右边大一个。。。瞬间明白。。。
全部代码:
#include<cstdio> #define M 100005 #define mid ( l+r )>>1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 __int64 color[M<<2],sum[M<<2]; void PushPlus(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushSub(int rt,int m){ if(color[rt]){ color[rt<<1]+=color[rt]; color[rt<<1|1]+= color[rt]; sum[rt<<1]+=color[rt]*(m-(m>>1)); sum[rt<<1|1]+=color[rt]*(m>>1); color[rt]=0; } } void Bulid(int l,int r,int rt){ color[l]=0; if(l == r){ scanf("%I64d",&sum[rt]); return ; } int m= mid; Bulid(lson); Bulid(rson); PushPlus(rt); } __int64 Query(int L,int R,int l,int r,int rt){ if(L<=l && r<=R){ return sum[rt]; } PushSub(rt,r-l+1); int m=mid; __int64 ans=0; if(L<=m) ans+=Query(L,R,lson); if(R>m) ans+=Query(L,R,rson); return ans; } void Change(__int64 x,int L,int R,int l,int r,int rt){ if(L<=l && r<=R){ sum[rt]+=((r-l+1)*x); color[rt]+=x; return ; } PushSub(rt,r-l+1); int m = mid; if(L<=m) Change(x,L,R,lson); if(R>m) Change(x,L,R,rson); PushPlus(rt); } int main(){ int n,m,a,b; __int64 c; char op[2]; while(~scanf("%d %d",&n,&m)){ Bulid(1,n,1); while(m--){ scanf("%s",op); if(op[0] == 'Q'){ scanf("%d %d",&a,&b); printf("%I64d\n",Query(a,b,1,n,1)); } else{ scanf("%d %d %I64d",&a,&b,&c); Change(c,a,b,1,n,1); } } } return 0; }