延迟标记(或者说懒惰标记),就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候。
#include <stdio.h>
#define maxn 100050
#define lson l , m , rt * 2
#define rson m+1 , r ,rt *2 +1
#define dem m = (l + r) / 2
__int64 sum[maxn*4];
__int64 col[maxn*4];
void PushUp(__int64 rt){
sum[rt] = sum[rt*2] + sum[rt*2+1];
}
void PushDown(__int64 rt,__int64 m)
{
if(col[rt]!=0)
{
col[rt*2] += col[rt]; //用+= 而非 = ,这样就避免了所加值得覆盖
col[rt*2+1] += col[rt];
sum[rt*2] += (m-m/2) * col[rt]; // 左孩子区间大,m表示的是父亲节点的区间大小,而非(l+r)
sum[rt*2+1] += (m/2) * col[rt];
col[rt] = 0;
}
}
void build(__int64 l,__int64 r,__int64 rt){
col[rt] = 0;
if(l == r){
scanf("%I64d",&sum[rt]);
return ;
}
__int64 dem;
build(lson);
build(rson);
PushUp(rt);
}
void update(__int64 L,__int64 R,__int64 add,__int64 l,__int64 r,__int64 rt){
if(L <= l && r <= R){
col[rt] += add;
sum[rt] += (r - l + 1)*add;
return ;
}
PushDown(rt,r-l+1);
__int64 dem;
if(L <= m) update(L,R,add,lson);
if(R > m) update(L,R,add,rson);
PushUp(rt);
}
__int64 query(__int64 L,__int64 R,__int64 l,__int64 r,__int64 rt)
{
if(L <=l && r <= R)
{
return sum[rt];
}
PushDown(rt,r-l+1); //查询时,遇到延时标记,也要将所加值向下更新至孩子节点。
__int64 dem;
__int64 res = 0;
if(L <= m) res += query(L,R,lson);
if(R > m) res += query(L,R,rson);
return res;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
__int64 n,T;
char str[3];
__int64 a,b,c;
while(scanf("%I64d%I64d",&n,&T)==2)
{
build(1,n,1);
while(T--)
{
scanf("%s",str);
if(str[0]=='Q') {
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",query(a,b,1,n,1));
}
else{
scanf("%I64d%I64d%I64d",&a,&b,&c);
update(a,b,c,1,n,1);
//for(int j=1;j<=10*3;j++)
// printf("%d ",sum[j]);
}
}
}
return 1;
}