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了