#include using namespace std; const int N = 100010; int n, q; // 线段树模板 #define int long long #define ls u << 1 #define rs u << 1 | 1 #define mid ((l + r) >> 1) struct Node { int l, r; int sum, add; // 区间总和,累加懒标记 } tr[N << 2]; // 更新统计信息 void pushup(int u) { tr[u].sum = tr[ls].sum + tr[rs].sum; } void pushdown(int u) { if (tr[u].add == 0) return; tr[ls].add += tr[u].add; tr[rs].add += tr[u].add; tr[ls].sum += (tr[ls].r - tr[ls].l + 1) * tr[u].add; tr[rs].sum += (tr[rs].r - tr[rs].l + 1) * tr[u].add; tr[u].add = 0; // 清除懒标记 } // 构建 void build(int u, int l, int r) { tr[u].l = l, tr[u].r = r; // 标记范围 if (l == r) { // 叶子 cin >> tr[u].sum; // 区间内只有一个元素l(r),区间和为read(),不需要记录向下的传递tag return; } build(ls, l, mid), build(rs, mid + 1, r); // 左右儿子构建 pushup(u); // 通过左右儿子构建后,向祖先节点反馈统计信息变化 } // 区间所有元素加上v void modify(int u, int L, int R, int v) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) { // 如果完整被覆盖 tr[u].sum += (r - l + 1) * v; tr[u].add += v; return; } if (l > R || r < L) return; // 如果没有交集 pushdown(u); // 下传懒标记 modify(ls, L, R, v), modify(rs, L, R, v); // 修改左,修改右 pushup(u); // 向上汇报统计信息 } // 查询 int query(int u, int L, int R) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) return tr[u].sum; // 如果完整被覆盖 if (l > R || r < L) return 0; // 如果没有交集 pushdown(u); // 下传懒标记 return query(ls, L, R) + query(rs, L, R); // 查询左+查询右 } signed main() { // 文件输入输出 #ifndef ONLINE_JUDGE freopen("P3372.in", "r", stdin); #endif // 加快读入 ios::sync_with_stdio(false), cin.tie(0); cin >> n >> q; // 构建线段树 build(1, 1, n); while (q--) { int op, l, r, v; cin >> op >> l >> r; if (op == 1) cin >> v, modify(1, l, r, v); else printf("%lld\n", query(1, l, r)); } return 0; }