Files
python/TangDou/AcWing/SegmentTree/P3372_XDS_Lazy-1_FeiQi.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

104 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
// 加法的懒标记,一般初始化为0,如果强行初始化为-1,则需要在代码中添加判断,否则在叠加过程中就会造成错误,在加法懒标记中,避免使用-1
int n, q;
#define ls u << 1
#define rs u << 1 | 1
struct Node {
int l, r;
LL sum, add; // 区间总和,加法懒标记
} tr[N << 2];
// 更新统计信息
void pushup(int u) {
tr[u].sum = tr[ls].sum + tr[rs].sum;
}
// 父节点向子孙节点传递信息
void pushdown(int u) {
if (tr[u].add == -1) return;
// 更新儿子的add信息,是为了更下一层的数据传递
// add传递到子段,节段的sum和需要按 区间长度*root.add 进行增加
if (tr[ls].add == -1)
tr[ls].add = tr[u].add;
else
tr[ls].add += tr[u].add;
tr[ls].sum += LL(tr[ls].r - tr[ls].l + 1) * tr[u].add;
if (tr[rs].add == -1)
tr[rs].add = tr[u].add;
else
tr[rs].add += tr[u].add;
tr[rs].sum += LL(tr[rs].r - tr[rs].l + 1) * tr[u].add;
// 别忘了清除懒标记
tr[u].add = -1;
}
// 构建
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r; // 标记范围
tr[u].add = -1; // 非得强行设置加法懒标记为-1
if (l == r) { // 叶子
scanf("%lld", &tr[u].sum); // 区间内只有一个元素l(r),区间和为read(),不需要记录向下的传递add
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid), build(rs, mid + 1, r); // 左右儿子构建
pushup(u); // 通过左右儿子构建后,向祖先节点反馈统计信息变化
}
// 以u为根,在区间[l,r]之间全都增加v
void modify(int u, int L, int R, int v) {
int l = tr[u].l, r = tr[u].r;
if (l >= L && r <= R) {
tr[u].sum += LL(r - l + 1) * v; // 总和增加
if (~tr[u].add) // 懒标记+d
tr[u].add += v;
else
tr[u].add = v;
return;
}
pushdown(u); // 如果自己身上有旧的add数值,在递归前需要将原add值pushdown到子孙节点去
int mid = (l + r) >> 1;
if (L <= mid) modify(ls, L, R, v); // 与左区间有交集
if (R > mid) modify(rs, L, R, v); // 与右区间有交集
pushup(u); // 将结果的变更更新到祖先节点
}
// 关键的查询操作
LL query(int u, int l, int r) {
if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
if (tr[u].l > r || tr[u].r < l) return 0;
pushdown(u);
return query(ls, l, r) + query(rs, l, r);
}
int main() {
// 文件输入输出
#ifndef ONLINE_JUDGE
freopen("P3372.in", "r", stdin);
#endif
scanf("%d %d", &n, &q);
// 构建线段树
build(1, 1, n);
while (q--) {
int a, b, c, d;
scanf("%d %d %d", &a, &b, &c);
if (b > c) swap(b, c);
if (a == 1)
scanf("%d", &d), modify(1, b, c, d);
else
printf("%lld\n", query(1, b, c));
}
return 0;
}