【洛谷P3372】【模板】【线段树1】

本文介绍了一种使用C++编写的最小累加和树(LCTree)的数据结构,用于高效地进行区间更新和查询操作。通过递归构建和维护树节点,它支持在给定区间内增加累加和并快速查询区间总和。适用于需要频繁区间修改和查询的应用场景,如动态区间统计问题。
摘要由CSDN通过智能技术生成
#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sophon、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值