同 Luogu P3373
注意如果写 pushup
的话不要越界
注意更新 sum
值的位置
# include <iostream>
# include <cstdio>
# define MAXN 100000+5
# define LL long long
using namespace std;
struct node{
int l, r;
int lazyA;
LL sum;
}a[MAXN<<2];
int lim;
void pushdown(int now){
if(a[now].lazyA){
a[now<<1].sum += (a[now<<1].r - a[now<<1].l + 1) * a[now].lazyA;
a[now<<1|1].sum += (a[now<<1|1].r - a[now<<1|1].l + 1) * a[now].lazyA;
a[now<<1].lazyA += a[now].lazyA, a[now<<1|1].lazyA += a[now].lazyA;
a[now].lazyA = 0;
}
return;
}
void build(int now, int l, int r){
a[now].l = l, a[now].r = r;
if(l == r){
scanf("%lld", &a[now].sum);
return;
}
int mid = ( l + r ) >> 1;
build(now<<1, l, mid);
build(now<<1|1, mid+1, r);
a[now].sum = a[now<<1].sum + a[now<<1|1].sum;
return;
}
void add(int now, int l, int r, LL val){
if(a[now].l >= l && a[now].r <= r){
a[now].sum += val * (a[now].r - a[now].l + 1);
a[now].lazyA += val; // 当前节点的区间被完全覆盖的情况
return;
}
pushdown(now);
int mid = (a[now].l + a[now].r) >> 1;
if(l <= mid) add(now<<1, l, r, val);
if(r > mid) add(now<<1|1, l, r, val);
// 因为上面的限定是完全覆盖所以 l r 打法不会出问题
a[now].sum = a[now<<1].sum + a[now<<1|1].sum;
return;
}
LL ask(int now, int l, int r){
if(a[now].l >= l && a[now].r <= r)
return a[now].sum;
pushdown(now);
LL sum = 0;
int mid = (a[now].l + a[now].r) >> 1;
if(l <= mid) sum += ask(now<<1, l, r);
if(r > mid) sum += ask(now<<1|1, l, r);
return sum;
}
int main(){
int n, m, opt, x, y, k;
scanf("%d%d", &n, &m);
build(1, 1, n);
for(int i = 1; i <= m; i++){
scanf("%d", &opt);
if(opt == 1){
scanf("%d%d%d", &x, &y, &k);
add(1, x, y, k);
}
else{
scanf("%d%d", &x, &y);
printf("%lld
", ask(1, x, y));
}
}
return 0;
}