学习线段树的第三天,懒标记写的还很不熟练
模板题不需要思路,直接上代码:
#include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int N = 1e5 + 5; int n, m; ll a[N]; struct Node { int l, r; ll sum, lazy; }st[N * 4]; void pushup (int u) { st[u].sum = st[u << 1].sum + st[u << 1 | 1].sum; } void pushdown (int x) { auto &u = st[x], &l = st[x << 1], &r = st[x << 1 | 1]; if (u.lazy) { l.lazy += u.lazy, l.sum += (ll)(l.r - l.l + 1) * u.lazy; r.lazy += u.lazy, r.sum += (ll)(r.r - r.l + 1) * u.lazy; u.lazy = 0; }//这里还很不熟练,特别是区间和 } void build (int u, int l, int r) { if (l == r) { st[u] = {l, r, a[r], 0}; //不需要往下传,所以pushdown 0 return; } st[u] = {l, r}; int mid = l + r >> 1; build (u << 1, l, mid); build (u << 1 | 1, mid + 1, r); pushup (u); } void modify (int u, int l, int r, int v) { if (st[u].l >= l && st[u].r <= r){ st[u].sum += (ll) (st[u].r - st[u].l + 1) * v; st[u].lazy += v;; return; } pushdown (u); int mid = st[u].l + st[u].r >> 1; if (l <= mid) modify (u << 1, l, r, v); if (r > mid) modify (u << 1 | 1, l, r, v); pushup (u); } ll query (int u, int l, int r) { if (st[u].l >= l && st[u].r <= r) return st[u].sum; pushdown (u); ll res = 0; int mid = st[u].l + st[u].r >> 1; if (l <= mid) res += query (u << 1, l, r); if (r > mid) res += query (u << 1 | 1, l, r); return res; } int main () { cin >> n >> m; for (int i = 1; i <= n; i ++) cin >> a[i]; build (1, 1, n); while (m --) { int op, x, y, k; cin >> op >> x >> y; if (op == 1) { cin >> k; modify (1, x, y, k); } else { cout << query (1, x, y) << endl; } } }