POJ 3468 A Simple Problem with Integers (线段树区间修改)

本文介绍了一种使用线段树实现区间修改与查询的算法,并提供了完整的C++代码实现。该算法能够高效地处理大规模数据范围内的区间加法及区间和查询问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:
线段树区间修改,然后让你求区间和的问题,但是题目有大坑,注意-1000000000≤ Ai ≤1000000000,要用long long型,虽然操作C增加c的范围只有-10000 ≤ c ≤ 10000,但是与它相关的参数都必须也要用long long型。。。注意了这个,剩下的就是线段树区间修改了。。。
ACcode:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
#define N 1000100
struct node
{
LL l;
LL r;
LL sum;
LL lazy;  //lazy标记记录更新值
}tree[N<<2];
LL a[N];
void pushdown(LL root, LL len)
{
	if (tree[root].lazy)
	{                                                            //将标记传递给左右子树  
		tree[root * 2].lazy += tree[root].lazy;
		tree[root * 2 + 1].lazy += tree[root].lazy;             // 更新左右子树的sum
		tree[root * 2].sum += tree[root].lazy*(len - (len / 2));
		tree[root * 2 + 1].sum += tree[root].lazy*(len / 2);
		tree[root].lazy = 0;                                    //注意标记清空
	}
}
void build(LL root, LL l, LL r)
{
	tree[root].l = l;
	tree[root].r = r;
	tree[root].lazy = 0;                     // lazy标记初始化
	if (l == r) { tree[root].sum = a[l]; return; }
	LL mid = (l + r) / 2;
	build(root * 2, l, mid);
	build(root * 2 + 1, mid + 1, r);
	tree[root].sum = tree[root * 2].sum + tree[root * 2 + 1].sum;
}
void update(LL root, LL l, LL r, LL c)
{
	int mid = (tree[root].r + tree[root].l) / 2;
	if (tree[root].l >= l&&tree[root].r <= r)         
	{
		tree[root].lazy += c;
		//更新本区间sum ,不然连续两次update会将标记堆积,而c值不同导致更新错误
		tree[root].sum += c*(tree[root].r - tree[root].l + 1);   
				return;
    }
    //将标记传递给左右子树,不然连续两次update会将标记堆积,而c值不同导致更新错误
	pushdown(root, tree[root].r - tree[root].l + 1);            
		if (l <= mid)
	{
		update(root * 2, l, r, c);
	}
	if (mid<r)
	{
		update(root * 2 + 1, l, r, c);
	}
	tree[root].sum = tree[root * 2].sum + tree[root * 2 + 1].sum;
}
LL query(LL root,LL l,LL r)
{
	int mid = (tree[root].l + tree[root].r) / 2;
	LL ans = 0;
	if (tree[root].l >= l&&tree[root].r <= r)
	{
		return tree[root].sum;
    }
//查询时将父亲节点的lazy传递给左右子树,更新区间,保证被查询的区间被已经被更新
	pushdown(root, tree[root].r - tree[root].l + 1);  	
	if (l <= mid)
	{
		ans += query(root * 2, l, r);
	}
	if (r>mid)
	{
		ans += query(root * 2 + 1, l, r);
	}
	tree[root].sum = tree[root * 2].sum + tree[root * 2 + 1].sum;
	return ans;
}
int main()
{
	LL i, x, y, z, n, m;
	char ch[10];
	while (scanf("%lld%lld", &n, &m) != EOF)
	{
		for (i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		    build(1, 1, n);
		for (i = 0; i<m; i++)
		{
			scanf("%s", ch);
			if (ch[0] == 'Q')
			{
				scanf("%lld%lld", &x, &y);
				printf("%lld\n", query(1, x, y));
			}
			else
			{
				scanf("%lld%lld%lld", &x, &y, &z);
				update(1, x, y, z);
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值