P3372 【模板】线段树 1

P3372 【模板】线段树 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

线段树的板子题,主要是背会板子,然后理解其中意思。

代码如下:

#include <iostream>
typedef long long LL;
LL n, a[100005], d[270000], b[270000]; 

void build(LL l, LL r, LL p)
{
	if (l == r)
	{
		d[p] = a[l];
		return ;
	}
	LL m = l + ((r - l) >> 1);
    build(l, m, p << 1), build(m + 1, r, (p << 1) | 1);  // 分别建立子树
	d[p] = d[p << 1] + d[(p << 1) | 1];
}

void update(LL l, LL r, LL c, LL s, LL t, LL p) // l 是操作的左端点,r 操作的右端点, c 对这个区间修改的值, s 是这个根对的左端点, t 是右端点
{
	if (l <= s && t <= r)
	{
		d[p] += (t - s + 1) * c, b[p] += c;
		return ;
	}
	LL m = s + ((t - s) >> 1);
	if (b[p]) // b[p] 是懒惰标记
		d[p << 1] += b[p] * (m - s + 1), d[(p << 1) | 1] += b[p] * (t - m), 
		b[p << 1] += b[p], b[(p << 1) | 1] += b[p];
	b[p] = 0;
	if (l <= m) update(l, r, c, s, m, p << 1);
	if (r > m) update(l, r, c, m + 1, t, (p << 1) | 1);
	d[p] = d[p << 1] + d[(p << 1) | 1]; // 计算该点的区间和
}

LL getsum(LL l, LL r, LL s, LL t, LL p)
{
	if (l <= s && t <= r) return d[p];
	LL m = s + ((t - s) >> 1);
	if (b[p])
		d[p << 1] += b[p] * (m - s + 1), d[(p << 1) | 1] += b[p] * (t - m), 
		b[p << 1] += b[p], b[(p << 1) | 1] += b[p];
	b[p] = 0;
	LL sum = 0;
	if (l <= m)
		sum = getsum(l, r, s, m, p << 1);
	if (r > m) sum += getsum(l, r, m + 1, t, (p << 1) | 1);
	return sum; 
}

signed main()
{
	std::ios::sync_with_stdio(false);
	LL q;
	std::cin >> n >> q;
	for (LL i = 1; i <= n; i ++)
	{
		std::cin >> a[i];
	}
	LL i1, i2, i3, i4;
	build(1, n, 1);
	while (q --)
	{
		std::cin >> i1 >> i2 >> i3;
		if (i1 == 2) std::cout << getsum(i2, i3, 1, n, 1) << "\n";
		else std::cin >> i4, update(i2, i3, i4, 1, n, 1);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值