// 输入格式:
// n m 数组范围是a[1]~a[n]操作有m个
// 1 L R v 表示设a[L]+=v, a[L+1]+v, ..., a[R]+=v
// 2 L R 查询a[L]~a[R]的sum
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 900000
ll sum[MAX*4], arr[MAX], tag[MAX*4];
ll x1, y2, k;//查询 / 修改 区间
int lc(int t) { return t<<1 ;}
int rc(int t) { return t<<1|1 ;}
void push_up_sum(ll o) { sum[o] = sum[lc(o)] + sum[rc(o)];}
// 向上不断维护区间操作
void build(ll o, ll L, ll R) {
tag[o] = 0;
if(L == R) sum[o] = arr[L];
else {
ll M = (L + R) >> 1;
build(lc(o), L, M);
build(rc(o), M+1, R);
push_up_sum(o);
}
}
void f(ll o, ll L, ll R, ll v) {
tag[o] += v;
sum[o] = sum[o] + v*(R-L+1);
//由于是这个区间统一改变,所以ans数组要加元素个数次啦
}
void push_down_sum(ll o, ll L, ll R) {
ll M = (L + R) >> 1;
f(lc(o), L, M, tag[o]);
f(rc(o), M+1, R, tag[o]);
tag[o] = 0;//传递
}
void update(ll o, ll L, ll R) {
if(x1 <= L && R <= y2) {
sum[o] += k*(R-L+1);
tag[o] += k;
return ;
}
push_down_sum(o, L, R);
ll M = (L + R) >> 1;
if(x1 <= M) update(lc(o), L, M);
if(y2 > M) update(rc(o), M+1, R);
push_up_sum(o);
}
ll query(ll o, ll L, ll R) {
ll res = 0;
if(x1 <= L && R <= y2) return sum[o];
ll M = (L + R) >> 1;
push_down_sum(o, L, R);
if(x1 <= M) res += query(lc(o), L, M);
if(y2 > M) res += query(rc(o), M+1, R);
return res;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &arr[i]);
build(1, 1, n);
int cmd;
for(int i = 1; i <= m; i++) {
scanf("%d",&cmd);
if(cmd == 1) {
scanf("%lld%lld%lld",&x1, &y2, &k);
update(1, 1, n);
} else{
scanf("%lld%lld",&x1,&y2);
printf("%lld\n", query(1, 1, n));
}
}
return 0;
}
luogu