线段树区间更新板子题:
加一个lazy数组用于存储。
加lazy原因:有的点并不需要往下更新
爆 long long
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100005
#define LL long long
LL tree[N<<2];
LL add[N<<2];
int n,m,l,r;
LL a;
char op[2];
void push_down(int root,int m)
{
if(add[root])
{
add[root<<1]+=add[root];
add[root<<1|1]+=add[root];
tree[root<<1]+=(m-(m>>1))*add[root];
tree[root<<1|1]+=(m>>1)*add[root];
add[root]=0;
return;
}
}
void push_up(int root)
{
tree[root]=tree[root<<1]+tree[root<<1|1];
}
void bulid(int root,int l,int r)
{
if(l == r)
{
scanf("%lld",&tree[root]);
return;
}
int mid = (l+r)>>1;
bulid(root<<1,l,mid);
bulid(root<<1|1,mid+1,r);
push_up(root);
}
void updata(int rootl,int rootr,int l,int r,int root,LL Add)
{
if(rootl<=l&&r<=rootr)
{
add[root]+=Add;
tree[root]+=(Add*(r-l+1));
return;
}
push_down(root,r-l+1);
int mid = (l+r)>>1;
if(rootl<=mid)updata(rootl,rootr,l,mid,root<<1,Add);
if(rootr>mid)updata(rootl,rootr,mid+1,r,root<<1|1,Add);
push_up(root);
}
LL Query(int rootl,int rootr,int l,int r,int root)
{
if(rootl<=l&&r<=rootr)
{
return tree[root];
}
push_down(root,r-l+1);
LL res=0;
int mid = (l+r)>>1;
if(rootl<=mid)res+=Query(rootl,rootr,l,mid,root<<1);
if(rootr>mid)res+=Query(rootl,rootr,mid+1,r,root<<1|1);
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(add,0,sizeof(add));
memset(tree,0,sizeof(tree));
bulid(1,1,n);
while(m--)
{
scanf("%s",op);
if(op[0] == 'Q')
{
scanf("%d%d",&l,&r);
printf("%lld\n",Query(l,r,1,n,1));
}
else
{
scanf("%d %d %lld",&l,&r,&a);
updata(l,r,1,n,1,a);
}
}
}
}