区间更新,就是为了说明一下向下更新。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int sum[maxn*4];
int add[maxn*4];
void PushUp(int rt)
{
sum[rt] = sum[rt*2] + sum[rt*2+1];
}
void PushDown(int l,int r,int rt)
{
if(add[rt])
{
int m = (l+r)/2;
add[rt*2] += add[rt];
add[rt*2+1] += add[rt];
sum[rt*2] += (m-l+1)*add[rt];
sum[rt*2+1] += (r-m)*add[rt];
add[rt] = 0;
}
}
void build(int l, int r, int rt)//建立线段树
{
if (l == r)
{
scanf("%d",&sum[rt]);
return;
}
int m = (l + r) / 2;
build(l, m, rt*2);
build(m + 1, r, rt*2+1);
PushUp(rt);
}
void update(int x,int y,int c, int l, int r, int rt)
{
if (x<=l && y>=r)
{
sum[rt] += c*(r-l+1);
add[rt] += c;
return;
}
PushDown(l,r,rt);
int m = (l + r) / 2;
if (x <= m)
update(x, y, c, l, m, rt*2);
if(y > m)
update(x, y, c, m + 1, r, rt*2+1);
PushUp(rt);
}
int query(int ll, int rr, int l, int r, int rt)//查询线段树
{
if (ll <= l && rr >= r) return sum[rt];
PushDown(l,r,rt);
int m = (l + r) / 2;
int ret = 0;
if (ll <= m)
ret += query(ll, rr, l, m, rt*2);
if (rr > m)
ret += query(ll, rr, m + 1, r, rt*2+1);
return ret;
}
int main()
{
int n,m,i,j;
char d[10];
while(scanf("%d%d",&n,&m)==2)
{
memset(add,0,sizeof(add));
memset(sum,0,sizeof(sum));
build(1, n, 1);
for(i=0;i<m;i++)
{
scanf("%s",d);
int x, y,z;
if (d[0] == 'Q')
{
scanf("%d%d", &x, &y);
int ans = query(x, y, 1, n, 1);
printf("%d\n", ans);
}
if (d[0] == 'C')
{
scanf("%d%d%d",&x,&y,&z);
update(x, y, z, 1, n, 1);
}
}
}
return 0;
}