线段树 区间修改
struct Tree {
int l, r;
ll val;
};
Tree node[maxn << 2];
ll lazy[maxn << 2];
ll a[maxn];
void push_up(int i) {
node[i].val = node[i << 1].val + node[i << 1 | 1].val;
}
void build(int i, int l, int r) {
node[i].l = l;
node[i].r = r;
if (l == r) {
node[i].val = a[l];
return;
}
int mid = l + r >> 1;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
push_up(i);
}
void push_down(int i,int m) {
if (lazy[i]) {
lazy[i << 1] += lazy[i];
lazy[i << 1 | 1] += lazy[i];
node[i << 1].val += lazy[i] * (m - (m >> 1));
node[i << 1 | 1].val += lazy[i] * (m >> 1);
lazy[i] = 0;
}
}
void update(int i, int l, int r,ll val) {
if (node[i].l > r || node[i].r < l) return;
if (node[i].l >= l && node[i].r <= r) {
lazy[i] += val;
node[i].val += (node[i].r - node[i].l + 1) * val;
return;
}
push_down(i, node[i].r - node[i].l + 1);
update(i << 1, l, r, val);
update(i << 1 | 1, l, r, val);
push_up(i);
}
ll get_sum(int i, int l, int r) {
if (node[i].l > r || node[i].r < l) return 0;
if (node[i].l >= l && node[i].r <= r) return node[i].val;
push_down(i, node[i].r - node[i].l + 1);
return get_sum(i << 1, l, r) + get_sum(i << 1 | 1, l, r);
}
int main() {
int n = readint();
int m = readint();
for (int i = 1; i <= n; i++)
a[i] = readll();
build(1, 1, n);
while (m--) {
int q = readint();
int x = readint();
int y = readint();
if (q == 1) {
ll val = readll();
update(1,x, y, val);
}
else {
Put(get_sum(1, x, y));
puts("");
}
}
}