#include using namespace std; const int N = 5e5 + 10; // 动态开点线段树 #define int long long #define ls tr[u].l #define rs tr[u].r #define mid ((l + r) >> 1) struct Node { int l, r; int sum, add; } tr[N << 1]; int root, idx; // 汇总统计信息 void pushup(int u) { tr[u].sum = tr[ls].sum + tr[rs].sum; } // 创建节点:节点号分配,懒标记初始化 void build(int &u) { if (u) return; u = ++idx; // tr[u].add = 0; } void pushdown(int &u, int l, int r) { if (tr[u].add == 0) return; // 如果没有累加懒标记,返回 build(ls); // 左儿子创建 build(rs); // 右儿子创建 // 懒标记下传 tr[ls].sum += tr[u].add * (mid - l + 1); // 区间和增加=懒标记 乘以 区间长度 tr[rs].sum += tr[u].add * (r - mid); tr[ls].add += tr[u].add; // 加法的懒标记可以叠加 tr[rs].add += tr[u].add; // 清除懒标记 tr[u].add = 0; } // 区间修改 void modify(int &u, int l, int r, int L, int R, int v) { build(u); // 动态开点 if (l >= L && r <= R) { // 如果区间被完整覆盖 tr[u].add += v; // 加法的懒标记可以叠加 tr[u].sum += v * (r - l + 1); // 区间和增加=懒标记 乘以 区间长度 return; } if (l > R || r < L) return; // 如果没有交集 // 下传懒标记 pushdown(u, l, r); // 分裂 modify(ls, l, mid, L, R, v), modify(rs, mid + 1, r, L, R, v); // 汇总 pushup(u); } // 区间查询 int query(int u, int l, int r, int L, int R) { if (l >= L && r <= R) return tr[u].sum; // 如果完整命中,返回我的全部 if (l > R || r < L) return 0; // 如果与我无关,返回0 pushdown(u, l, r); return query(ls, l, mid, L, R) + query(rs, mid + 1, r, L, R); } /* 参考答案: 11 8 20 */ signed main() { #ifndef ONLINE_JUDGE freopen("P3372.in", "r", stdin); #endif // 加快读入 ios::sync_with_stdio(false), cin.tie(0); int n, m; cin >> n >> m; // n个节点,m次操作 for (int i = 1; i <= n; i++) { int x; cin >> x; modify(root, 1, n, i, i, x); // 单点修改,赋初值 } while (m--) { int op, l, r; cin >> op >> l >> r; if (op == 1) { int x; cin >> x; modify(root, 1, n, l, r, x); //[l,r]区间修改为x } else cout << query(root, 1, n, l, r) << endl; // 区间sum和 } return 0; }