#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
int n, m, root;
struct MergeSegmentTree {
#define lid lson[id]
#define rid rson[id]
int lson[5211314] = {}, rson[5211314] = {}, tot = 0;
ll sum[5211314] = {}, lazy[5211314] = {};
inline void PushUp(int id) {
sum[id] = sum[lid] + sum[rid];
return;
}
inline void PushDown(int id, int l, int r) {
if (lazy[id] != 0) {
int mid = (l + r) >> 1;
sum[lid] += (mid - l + 1) * lazy[id];
sum[rid] += (r - mid) * lazy[id];
lazy[lid] += lazy[id];
lazy[rid] += lazy[id];
lazy[id] = 0;
}
return;
}//下放
void UpdatePoint(int &id, int l, int r, int pos, int num) {
if (id == 0) ++ tot, id = tot;
if (l == r) {
sum[id] = num;
return;
}
PushDown(id, l, r);
int mid = (l + r) >> 1;
if (pos <= mid) UpdatePoint(lid, l, mid, pos, num);
else UpdatePoint(rid, mid + 1, r, pos, num);
PushUp(id);
return;
}//单点更新
void UpdateInterval(int &id, int l, int r, int vl, int vr, int num) {
if (id == 0) ++ tot, id = tot;
if (vl <= l && r <= vr) {
sum[id] += (r - l + 1) * num;
lazy[id] += num;
return;
}
PushDown(id, l, r);
int mid = (l + r) >> 1;
if (vl <= mid) UpdateInterval(lid, l, mid, vl, vr, num);
if (mid + 1 <= vr) UpdateInterval(rid, mid + 1, r, vl, vr, num);
PushUp(id);
return;
}//区间更新
ll Query(int &id, int l, int r, int vl, int vr) {
if (id == 0) ++ tot, id = tot;
if (vl <= l && r <= vr) {
return sum[id];
}
PushDown(id, l, r);
int mid = (l + r) >> 1;
ll ans = 0;
if (vl <= mid) ans += Query(lid, l, mid, vl, vr);
if (mid + 1 <= vr) ans += Query(rid, mid + 1, r, vl, vr);
PushUp(id);
return ans;
}//查询
int Merge(int a1, int b1, int l, int r) {
if ((a1 | b1) == 0) return (a1 | b1);
if (l == r) {
sum[a1] += sum[b1];
lazy[a1] += sum[b1];
return a1;
}
int mid = (l + r) >> 1;
PushDown(a1, l, r), PushDown(b1, l, r);
lson[a1] = Merge(lson[a1], lson[b1], l, mid);
rson[a1] = Merge(rson[a1], rson[b1], mid + 1, r);
PushUp(a1);
return a1;
}//合并
#undef lid
#undef rid
}tree;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i) {
ll ask;
scanf("%lld", &ask);
tree.UpdatePoint(root, 1, n, i, ask);
}
for (int i = 1, op, x, y; i <= m; ++ i) {
ll k;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%lld", &x, &y, &k);
tree.UpdateInterval(root, 1, n, x, y, k);
}
else {
scanf("%d%d", &x, &y);
printf("%lld\n", tree.Query(root, 1, n, x, y));
}
}
return 0;
}