基础&进阶 线段树学习笔记(一) | P3372 【模板】线段树 1 题解( 二 )

查询其实和修改很像 。(不妨肉眼观查一下)在该结点所管辖的区间完全被覆盖时,直接返回区间和 。若未被完全覆盖,则下传懒标记,分左右儿子考虑,统计总答案并返回值 。是不是 so easy?
于是你愉快地切了这题 。

完整代码,点击查看#include <bits/stdc++.h>using namespace std;#define ll long long#define pii pair<int, int>inline ll read() { ll s = 0, w = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') w = -1; c = getchar();} while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar(); return s * w;}const int N = 100010;int n, m, a[N];struct SegmentTree { ll sum[N << 2], lazy[N << 2]; int l[N << 2], r[N << 2]; void update(int rt) {sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void pushdown(int rt) {if (!lazy[rt]) return ;sum[rt << 1] += (r[rt << 1] - l[rt << 1] + 1) * lazy[rt], lazy[rt << 1] += lazy[rt];sum[rt << 1 | 1] += (r[rt << 1 | 1] - l[rt << 1 | 1] + 1) * lazy[rt], lazy[rt << 1 | 1] += lazy[rt];lazy[rt] = 0;update(rt); } void build(int rt, int L, int R) {l[rt] = L, r[rt] = R;if (L == R) {sum[rt] = a[L];return ;}int mid = L + R >> 1;build(rt << 1, L, mid), build(rt << 1 | 1, mid + 1, R);update(rt); } void change(int rt, int L, int R, int x) {if (L <= l[rt] && r[rt] <= R) {sum[rt] += (r[rt] - l[rt] + 1) * x;lazy[rt] += x;return ;}pushdown(rt);if (L <= r[rt << 1]) change(rt << 1, L, R, x);if (l[rt << 1 | 1] <= R) change(rt << 1 | 1, L, R, x);update(rt); } ll query(int rt, int L, int R) {if (L <= l[rt] && r[rt] <= R) return sum[rt];pushdown(rt);ll res = 0;if (L <= r[rt << 1]) res += query(rt << 1, L, R);if (l[rt << 1 | 1] <= R) res += query(rt << 1 | 1, L, R);return res; }} tree;int main() { n = read(), m = read(); for (int i = 1; i <= n; i++) a[i] = read(); tree.build(1, 1, n); while (m--) {int op = read();if (op == 1) {int l = read(), r = read(), x = read();tree.change(1, l, r, x);}if (op == 2) {int l = read(), r = read();printf("%lld\n", tree.query(1, l, r));} } return 0;}
现在,你学会了区间修改区间查询的线段树,不如想想 单点修改区间查询 和 区间修改单点查询 怎么写?(为什么没有单点修改单点查询线段树呢(小声)
点击继续研究线段树 - 线段树学习笔记(基础&进阶)(二)

经验总结扩展阅读