POJ 3468

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
Hint
The sums may exceed the range of 32-bit integers.

您有N个整数A1,A2,…,AN。 您需要处理两种操作。 一种操作类型是在给定间隔内向每个数字添加一些给定数字。 另一种是在给定的时间间隔内求和。

输入值
第一行包含两个数字N和Q。1≤N,Q≤100000。
第二行包含N个数字,即A1,A2,…,AN的初始值。 -1000000000≤Ai≤1000000000。
接下来的每条Q线代表一个操作。
“ C a b c”是指将c加到Aa,Aa + 1,…,Ab中的每一个上。 -10000≤c≤10000。
“ Q a b”是指查询Aa,Aa + 1,…,Ab的和。

输出量
您需要依次回答所有Q命令。 一行回答。

输入
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
输出
4
55
9
15
提示
总和可能超出32位整数的范围。

题目大意:
输入n和m,表示n个数和m个询问,对于每个询问:

  • “ C a b c”是指将c加到Aa,Aa + 1,…,Ab中的每一个上。 -10000≤c≤10000。
  • “ Q a b”是指查询Aa,Aa + 1,…,Ab的和。

当遇到Q的时候输出区间的和。

解题思路:
这道题是线段树的一道区间求和和区间更新,因为在区间更新时,普通遍历线段树一定会超时,我们这里用一个lazy数组用于存放要更新的值,每次用到这个值的时候再分配到子节点,我们什么时候用到这个区间什么时候就把lazy的值下放到子节点,举个例子,比如一共有12个数,第一次给 [ 1 6 ] 每一个加3,就让这个节点的lazy值为3,就不往下放了,当再次操作和1-6区间有重合时,再把这个节点的lazy值下放到子节点。关于lazy数组:因为一个树中有好几个元素,所以我们用结构体存储这棵树,我们要存放当前节点的值,当前节点的lazy值和区间长度,为什么要存区间长度,因为在给这个点的lazy赋值时,这个点的和一定会加上区间长度*lazy值,因为区间长度即是要更新值的个数。就一定不会超时。AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll _max=1e5+50;
ll arr[_max];
struct ttt
{
	ll lazy,sum;
	int len;
}tree[5*_max];
int main()
{
	void build_tree(int,int,int);
	ll query(int,int,int,int,int);
	void update(int,int,int,int,int,int);
	int n,m;
	scanf("%d%d",&n,&m);
	for ( int i = 0; i < n; i++)
	  scanf("%lld",&arr[i]);
	getchar();
	build_tree(0,0,n-1);
	while(m--)
	{
		char k;
		int a,b,c;
		scanf("%c",&k);
		if(k=='Q')
		{
			scanf("%d%d",&a,&b);
			getchar();
			ll sum=query(0,0,n-1,a-1,b-1);
			printf("%lld
",sum);
		}
		else
		{
			scanf("%d%d%d",&a,&b,&c);
			getchar();
			update(0,0,n-1,a-1,b-1,c);
		}
	}
 	//system("pause");
	return 0;
}
void build_tree(int node ,int start ,int end)
{
	tree[node].lazy=0;
	tree[node].len=end-start+1;
	if(start==end)
	{
		tree[node].sum=arr[start];
		return;
	}
	int ln = node*2+1;
	int rn = node*2+2;
	int mid=(start+end)>>1;
	build_tree(ln,start,mid);
	build_tree(rn,mid+1,end);
	tree[node].sum=tree[ln].sum+tree[rn].sum;
}
void lazzy(int node)
{
	if(tree[node].lazy)
	{
		tree[node*2+1].lazy+=tree[node].lazy;
		tree[node*2+2].lazy+=tree[node].lazy;
		tree[node*2+1].sum+=tree[node].lazy*tree[node*2+1].len;
		tree[node*2+2].sum+=tree[node].lazy*tree[node*2+2].len;
		tree[node].lazy=0;
	}
}
ll query(int node, int start, int end, int l, int r)
{
	if (l<=start&&r>=end)
      return tree[node].sum;
	lazzy(node);
    int ln=node*2+1;
    int rn=node*2+2;
    int mid=(start+end)>>1;
	ll suml,sumr;
	suml=sumr=0;
	if(l<=mid)
      suml=query(ln,start,mid,l,r);
    if(r>mid)
	  sumr=query(rn,mid+1,end,l,r);
    return suml+sumr;
}
void update(int node,int start,int end,int l,int r,int x)
{
	if(l<=start&&r>=end)
	{
		tree[node].lazy+=x;
		tree[node].sum+=x*tree[node].len;
		return;
	}
	lazzy(node);
	int ln=node*2+1;
    int rn=node*2+2;
	int mid=(start+end)>>1;
	if(l<=mid)
	  update(ln,start,mid,l,r,x);
	if(r>mid)
	  update(rn,mid+1,end,l,r,x);
	tree[node].sum=tree[ln].sum+tree[rn].sum;
}
原文地址:https://www.cnblogs.com/Hayasaka/p/14294277.html