目录
题目-一个简单的整数问题2

问题分析
定义线段树需要维护的信息
cpp
struct Node {
int l, r;
LL sum, add;
};
sum代表考虑当前节点和子节点上的所有标记 的当前区间和, add延迟标记表示给当前区间的所有儿子 都加上add
算法步骤
- 定义线段树
- 实现线段树延迟标记更新操作
- 实现线段树
push up操作 - 实现区间修改操作, 注意要进行懒标记下传
- 实现区间查询操作, 再查询的时候也需要下传懒标记
代码实现
cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int n, m;
LL w[N];
struct Node {
int l, r;
LL sum, add;
} tr[N << 2];
void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void pushdown(int u) {
Node &ls = tr[u << 1], &rs = tr[u << 1 | 1];
if (tr[u].add) {
ls.add += tr[u].add, rs.add += tr[u].add;
ls.sum += (LL) (ls.r - ls.l + 1) * tr[u].add;
rs.sum += (LL) (rs.r - rs.l + 1) * tr[u].add;
tr[u].add = 0;
}
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = {l, r, w[l], 0};
return;
}
tr[u] = {l, r, 0,0};
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int ql, int qr, LL val) {
// 注意区间修改的时候, 需要修改sum和add, 因为add只会作用于子区间
if (tr[u].l >= ql && tr[u].r <= qr) {
tr[u].sum += (tr[u].r - tr[u].l + 1) * val;
tr[u].add += val;
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (ql <= mid) modify(u << 1, ql, qr, val);
if (qr > mid) modify(u << 1 | 1, ql, qr, val);
pushup(u);
}
LL query(int u, int ql, int qr) {
if (tr[u].l >= ql && tr[u].r <= qr) return tr[u].sum;
LL ans = 0;
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
if (ql <= mid) ans += query(u << 1, ql, qr);
if (qr > mid) ans += query(u << 1 | 1, ql, qr);
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> w[i];
build(1, 1, n);
while (m--) {
char c;
cin >> c;
if (c == 'C') {
int l, r, x;
cin >> l >> r >> x;
modify(1, l, r, x);
}
else {
int l, r;
cin >> l >> r;
cout << query(1, l, r) << '\n';
}
}
return 0;
}