模板题,导致发现之前的模板写错了,更新函数maintain中的叶子节点需要特判。
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn = 200000 + 10;
ll sumv[3*maxn], a[maxn], addv[3*maxn], v, sum;
int n, q, X, Y;
void creat(int o,int l, int r){
if(l == r){
sumv[o] = a[l];
return;
}
else{
int m = l + (r-l)/2;
creat(o*2, l, m);
creat(o*2+1, m+1, r);
sumv[o] = sumv[o*2] + sumv[o*2+1];
}
}
void maintain(int o, int l, int r){
int lc = o*2;
int rc = o*2+1;
//sumv[o] = 0;
if(r > l){
sumv[o] = sumv[lc] + sumv[rc];
sumv[o] += addv[o] * (r-l+1);
}
else{
sumv[o] += addv[o];
addv[o] = 0;
}
}
void update(int o, int l, int r){
if(X <= l && r <= Y){
addv[o] += v;
}
else{
int m = l + (r-l)/2;
if(X <= m) update(o*2, l, m);
if(Y > m) update(o*2+1, m+1, r);
}
maintain(o, l, r);
}
void query(int o, int l, int r, int add){
if(X <= l && r <= Y){
sum += sumv[o] + add * (r-l+1);
}
else{
int m = l + (r-l)/2;
if(X <= m) query(o*2, l, m, add+addv[o]);
if(Y > m) query(o*2+1, m+1, r, add+addv[o]);
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
creat(1, 1, n);
scanf("%d", &q);
int p;
for(int i = 1; i <= q; i++){
scanf("%d", &p);
if(p == 1){
scanf("%d %d %lld", &X, &Y, &v);
update(1, 1, n);
}
else{
scanf("%d %d", &X, &Y);
sum = 0;
query(1, 1, n, 0);
printf("%lld\n", sum);
}
}
return 0;
}