poj 3468 A Simple Problem with Integers(线段树)

Description

You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+1, … , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output

4
55
9
15
线段树入门:主要是lazy-tag的方法

#include<stdio.h>

typedef long long ll;
const ll maxn = 100007;

ll tree[4 * 100007 ], add[4 * 100007];
ll a[100007];
 
void Build_tree(int start,int end,int u)
{
	if(start==end)
	{
		tree[u] = a[end];
		return;
	}
	Build_tree(start, (start + end) / 2, u * 2);//构造左子树
	Build_tree((start + end) / 2 + 1, end, u * 2 + 1);//构造右子树
	tree[u] = tree[u * 2] + tree[u * 2+1];
}
//lazy-tag方法
void push_down(int u,int m)
{
	if(add[u])
	{
		add[u<<1] += add[u];//
		add[ u<<1 | 1 ] += add[u];//
		tree[u << 1] += (m - (m >> 1)) * add[u];//
		tree[u << 1 | 1] += (m >> 1) * add[u];
		add[u] = 0;//取消本层标记
	}
}

void update(int L,int R,ll c,int u,int start,int end)//在区间L到R+c
{
	if(L<=start&&R>=end)
	{
		tree[u] += (end - start + 1) * c;//树的区间
		add[u] += c;
		return;
	}
	push_down(u, end - start + 1);//向下更新
	int mid = (start + end) >> 1;
	if(L<=mid)
		update(L, R, c, u * 2, start, mid);
	if(R>mid)
		update(L, R, c, u * 2 + 1, mid + 1, end);
	tree[u] = tree[u * 2] + tree[u * 2 + 1];
}

ll querry(int a, int b, int l, int r, int u)
{
//printf("l=%d  r=%d  u=%d\n", l, r,u);
	if(a<=l&&b>=r)
		return tree[u];
	push_down(u, r - l + 1);
	int mid = (l + r) >> 1;
	ll ans = 0;
	if(a<=mid)
		ans += querry(a, b, l, mid, u * 2);
	if(b>mid)
		ans += querry(a, b, mid + 1, r, u * 2 + 1);
	return ans;
}


int main()
{
	freopen("11.txt", "r", stdin);
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1;i<=n;i++)
		scanf("%lld", &a[i]);
	Build_tree(1, n, 1);
	// for (int i = 1;i<30;i++)
	// 	printf("%d   %lld\n",i, tree[i]);建树没有问题

		char s[2];
	while(m--)
	{
		scanf("%s", s);
		int a, b;
		if(s[0]=='C')
		{
			ll c;
			scanf("%d%d%lld", &a, &b, &c);
			update(a, b, c, 1, 1, n);
		}
		else
		{
			scanf("%d%d", &a, &b);
			printf("%lld\n", querry(a, b, 1, n, 1));
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值