洛谷 P3372 【模板】线段树 1
P3372 【模板】线段树 1
带懒标记的线段树
学习线段树的第三天,懒标记写的还很不熟练
模板题不需要思路,直接上代码:
#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;
}
}
}