#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
#define lcd tree[pos * 2]
#define rcd tree[pos * 2 + 1]
ll a[N];
struct node {
int l, r;
ll val, tag;
}tree[N * 4];
void build(int pos, int l, int r)
{
tree[pos].l = l;
tree[pos].r = r;
if (l == r) {
tree[pos].val = a[l];
return;
}
int mid = l + (r - l) / 2;
build(pos * 2, l, mid);
build(pos * 2 + 1, mid + 1, r);
tree[pos].val = lcd.val + rcd.val;
}
void pushdown(int pos)
{
if (tree[pos].tag)
{
lcd.val += tree[pos].tag * (lcd.r - lcd.l + 1);
rcd.val += tree[pos].tag * (rcd.r - rcd.l + 1);
lcd.tag += tree[pos].tag;
rcd.tag += tree[pos].tag;
tree[pos].tag = 0;
}
}
void updata(int pos)
{
tree[pos].val = lcd.val + rcd.val;
}
void add(int pos, int l, int r, ll val)
{
if (l <= tree[pos].l && r >= tree[pos].r)
{
tree[pos].val += (tree[pos].r - tree[pos].l + 1) * val;
tree[pos].tag += val;
return;
}
pushdown(pos);//必须在if之后,不能对叶子结点pushdown
if (tree[pos].l == tree[pos].r)
return;
int mid = tree[pos].l + (tree[pos].r - tree[pos].l) / 2;
if (l <= mid)
add(pos * 2, l, r, val);
if (r >= mid + 1)
add(pos * 2 + 1, l, r, val);
updata(pos);
}
ll query(int pos, int l, int r)
{
if (l <= tree[pos].l && r >= tree[pos].r)
return tree[pos].val;
pushdown(pos);
ll sum = 0;
int mid = tree[pos].l + (tree[pos].r - tree[pos].l) / 2;
if (l <= mid)
sum += query(pos * 2, l, r);
if (r >= mid + 1)
sum += query(pos * 2 + 1, l, r);
return sum;
}
int n, m;
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, 1, n);
while (m--)
{
int op; cin >> op;
if (op == 1) {
int x, y;
ll k;
cin >> x >> y >> k;
add(1, x, y, k);
}
else {
int x, y;
cin >> x >> y;
cout << query(1, x, y) << '\n';
}
}
return 0;
}
【洛谷P3372】【模板】【线段树1】
最新推荐文章于 2024-09-21 14:48:47 发布
本文介绍了一种使用C++编写的最小累加和树(LCTree)的数据结构,用于高效地进行区间更新和查询操作。通过递归构建和维护树节点,它支持在给定区间内增加累加和并快速查询区间总和。适用于需要频繁区间修改和查询的应用场景,如动态区间统计问题。
摘要由CSDN通过智能技术生成