POJ-3468-A Simple Problem with Integers

POJ-3468

A Simple Problem with Integers

这道题线段树模板题,线段树区间求和区间修改

题目多次询问,遇到C修改区间,遇到Q求和
lay-tag方法
sum[]数组记录区间和
add[]记录结点是否用到tag原理。向下更新的时候重新将值置0.
同样记得向上更新
lazy-tag原理是当修改的是一整块区间时,只对这个线段区间进行整体修改,内部的每个元素先不做修改,只有当这部分线段的一致性被破坏时,才传递修改子区间。例如一个区间包含线段区间的一部分时。处于交错状态时需要传递修改子区间。

实现代码如下:

#include <iostream>
#include <cstdio> 
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

ll sum[N << 2], add[N << 2];
int n, m;

void push_up(int rt)//向上更新 
{
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void push_down(int rt, int m)//更新子结点 
{
	if (add[rt])
	{
		add[rt << 1] += add[rt];
		add[rt << 1 | 1] += add[rt];
		sum[rt << 1] += (m - (m >> 1)) * add[rt];
		sum[rt << 1 | 1] += (m >> 1) * add[rt];
		add[rt] = 0;//取消本层标记 
	}
}

void build(int l, int r, int rt)
{
	add[rt] = 0;
	if (l == r)
	{
		scanf ("%lld", &sum[rt]);
		return ;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	push_up(rt);
}

void update(int a, int b, ll c, int l, int r, int rt)
{
	if (a <= l && b >= r)
	{
		sum[rt] += (r - l + 1) * c;
		add[rt] += c;
		return ;
	}
	push_down(rt, r - l + 1);//向下更新
	int mid = (l + r) >> 1;
	if (a <= mid)//分成两半继续深入 
	{
		update(a, b, c, lson);
	} 
	if (b > mid)
	{
		update(a, b, c, rson);
	}
	push_up(rt);//向上更新 
}

ll query(int a, int b, int l, int r, int rt)
{
	if (a <= l && b >= r)
	{
		return sum[rt];
	}
	push_down(rt, r - l + 1);
	int mid = (r + l) >> 1;
	ll ans = 0;
	if (a <= mid)
	{
		ans += query(a, b, lson);
	}
	if (b > mid)
	{
		ans += query(a, b, rson);
	}
	return ans;
}

int main()
{
	cin >> n >> m;
	build(1, n, 1);
	while (m--)
	{
		char str[2];
		int a, b;
		ll c;
		scanf ("%s", str);
		if (str[0] == 'C')
		{
			scanf ("%d%d%lld", &a, &b, &c);
			update(a, b, c, 1, n, 1);
		}
		else
		{
			scanf ("%d%d", &a, &b);
			cout << query(a, b, 1, n, 1) << endl;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

娃娃酱斯密酱

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

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

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

打赏作者

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

抵扣说明:

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

余额充值