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.
题意:
给定一串数字,两种区间操作,询问区间和,区间内元素增加
思路:
线段树,区间更新
#include <stdio.h>
#include <string.h>
struct node
{
long long left, right, lazy;
long long data;
}tree[4000055];
long long a[1000055];
void build(long long l,long long r, long long k) //普通方法建树即可
{
tree[k].left = l;
tree[k].right = r;
tree[k].lazy = 0;
if(l==r)
{
tree[k].data = a[l];
return;
}
else
{
long long mid = (l + r) / 2;
build(l, mid, 2 * k);
build(mid+1, r, 2 * k + 1);
tree[k].data = tree[2 * k].data + tree[2 * k + 1].data;
}
}
void pushdown(long long k) //把节点k的lazy值传给他的孩子,有需要时向下更新
{
tree[2 * k].lazy += tree[k].lazy;
tree[2 * k + 1].lazy += tree[k].lazy;
tree[2 * k].data += (tree[2 * k].right - tree[2 * k].left + 1) * tree[k].lazy;
tree[2 * k + 1].data += (tree[2 * k + 1].right - tree[2 * k + 1].left + 1) * tree[k].lazy;
tree[k].lazy = 0;
}
long long ask(long long x, long long y, long long k)
{
if(tree[k].lazy != 0) pushdown(k); //看到节点,向下更新,
//否则如果走下面else的话,节点k的lazy传不到下面的小区间
if(x <= tree[k].left && tree[k].right <= y) return tree[k].data;
else
{
long long mid = (tree[k].left + tree[k].right) / 2;
if(y <= mid) return ask(x, y, 2 * k);
else if(x > mid) return ask(x, y, 2 * k + 1);
else return ask(x, y, 2 * k) + ask(x, y, 2 * k + 1);
}
}
void add(long long x, long long y, long long z, long long k)
{
if(x <= tree[k].left && tree[k].right <= y)
{
tree[k].data += (tree[k].right - tree[k].left + 1) * z; //data不要忘记乘区间元素个数
tree[k].lazy += z;
return;
}
else
{
if(tree[k].lazy != 0) pushdown(k); //这里必须要pushdown的,不加会WA
//只要看到新的区间,就pushdown一下好了,更新也没什么大坏处
long long mid = (tree[k].left + tree[k].right) / 2;
if(y <= mid) add(x, y, z, 2*k);
else if(x > mid) add(x, y, z, 2*k+1);
else
{
add(x, y, z, 2*k);
add(x, y, z, 2*k+1);
}
tree[k].data = tree[2*k].data + tree[2*k+1].data; //下面的节点更新完成,上面的自然要变
}
}
int main()
{
long long n, m, i, x, y, z;
char c[10];
scanf("%lld %lld", &n, &m);
for(i=1;i<=n;i++)
{
scanf("%lld", &a[i]);
}
build(1, n, 1);
while(m--)
{
scanf(" %s", c);
if(c[0]=='Q')
{
scanf("%lld %lld", &x, &y);
printf("%lld\n", ask(x, y, 1));
}
else if(c[0]=='C')
{
scanf("%lld %lld %lld", &x, &y, &z);
add(x, y, z, 1);
}
}
return 0;
}
WA了十多遍,
原因是一开始在判断是否要向下pushdown的时候写成了if(str[k].lazy>0),
当需要区间减小的时候进不去就WA了