题意:两种操作:一、区间中每个元素加一个值,二、查询区间元素之和
思路:线段树成段增减,区间求和
#include <stdio.h>
#include <string.h>
#define lson l ,m, rt * 2
#define rson m + 1, r, rt * 2 + 1
long long sum[400005], col[400005];
void pushup(int rt)
{//向上更新
sum[rt] = sum[rt * 2] + sum[rt * 2 + 1];
}
void pushdown(int rt, int len)
{//使用延迟标记
if(col[rt])
{
col[rt * 2] += col[rt];
col[rt * 2 + 1] += col[rt];
sum[rt * 2] += col[rt] * (len - len / 2);
sum[rt * 2 + 1] += col[rt] * (len / 2);
col[rt] = 0;
}
}
void build(int l, int r, int rt)
{//建树,rt为结点序号,l-r为该节点所代表的区间范围
col[rt] = 0;
if(l == r)
{
scanf("%I64dd", &sum[rt]);
return;
}
int m = (l + r) / 2;
build(lson);
build(rson);
pushup(rt);
}
void update(int L, int R, long long n, int l, int r, int rt)
{
if(L <= l && r <= R)
{//当前节点代表的区间 在 查询的区间 中,则更新当前区间的所有值
col[rt] += n; //延迟标记,不更新到底,下次更新或查询到的时候再向下更新
sum[rt] += (r - l + 1) * n;
return;
}
pushdown(rt, r - l + 1);
int m = (l + r) / 2;
if(L <= m) update(L, R, n, lson); //左半段区间需要查询
if(R > m) update(L, R, n, rson); //右半段区间需要查询
pushup(rt);
}
long long query(int L, int R, int l, int r, int rt)
{//区间和查询
if(L <= l && r <= R)
{
return sum[rt];
}
pushdown(rt, r - l + 1);
long long res = 0;
int m = (l + r) / 2;
if(L <= m) res += query(L, R, lson);
if(R > m) res += query(L, R, rson);
return res;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int n, q, a, b;
long long c;
char op;
while(scanf("%d%d", &n, &q) != EOF)
{
build(1, n, 1);
while(q--)
{
scanf(" %c %d%d", &op, &a, &b);
if(op == 'C')
{
scanf("%I64d", &c);
update(a, b, c, 1, n, 1);
}
else
{
printf("%I64d\n", query(a, b, 1, n, 1));
}
}
}
return 0;
}