题意很简单的,就是区间更新,区间求和
自己写的代码总体上都对了,但还是因为细节没处理好
仍然使用延迟标记的概念,这里用add为0表示不需要从当前节点向下更新
若add不为0时需要向下更新
我犯的一个错误就是向下更新过程中把父节点的add值赋给了子节点的add值
其实应该是累加才对,而且在更新子节点的val时也应该是(r-l+1)*node[rt].add
而不是乘以这个子节点的add,这样才可以保证不加重
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 100100
#define LL long long
using namespace std;
struct Node {
LL add, val;
}node[MAXN<<2];
void PushUp(int rt) {
node[rt].val = node[rt<<1].val + node[rt<<1|1].val;
}
void PushDown(int rt, int m) {
if(node[rt].add) {
node[rt<<1].add += node[rt].add;
node[rt<<1|1].add += node[rt].add;
node[rt<<1].val += (m-(m>>1)) * node[rt].add;
node[rt<<1|1].val += (m>>1) * node[rt].add;
node[rt].add = 0;
}
}
void build(int l, int r, int rt) {
node[rt].add = 0;
if(l == r) {
scanf("%lld", &node[rt].val);
return ;
}
int m = (l+r) >> 1;
build(l, m, rt<<1);
build(m+1, r, rt<<1|1);
PushUp(rt);
}
void update(LL L, LL R, LL add, int l, int r, int rt) {
if(L<=l && r<=R) {
node[rt].add += add;
node[rt].val += (r-l+1) * add;
//printf("node[%d].val = %lld\n", rt, node[rt].val);
return ;
}
PushDown(rt, r-l+1);
int m = (l+r) >> 1;
if(L <= m)
update(L, R, add, l, m, rt<<1);
if(R > m)
update(L, R, add, m+1, r, rt<<1|1);
PushUp(rt);
}
LL query(LL L, LL R, int l, int r, int rt) {
if(L<=l && r<=R)
return node[rt].val;
PushDown(rt, r-l+1);
int m = (l+r) >> 1;
LL ans = 0;
if(L <= m) {
ans += query(L, R, l, m, rt<<1);
}
if(R > m)
ans += query(L, R, m+1, r, rt<<1|1);
return ans;
}
int main(void) {
char ch;
int n, q;
LL a, b, c;
while(scanf("%d%d", &n, &q) != EOF) {
build(1, n, 1);
while(q--) {
scanf(" %c", &ch);
if(ch == 'Q') {
scanf("%lld%lld", &a, &b);
printf("%lld\n", query(a, b, 1, n, 1));
} else {
scanf("%lld%lld%lld", &a, &b, &c);
update(a, b, c, 1, n, 1);
}
}
}
return 0;
}