问题
给出长度为N的数列。数列的初始值是1, 2, 3, …, N。但是这个数列频繁地发生变更,要求出这期间某个连续部分的和。
假设N是5的情况。初始为1, 2, 3, 4, 5。在这个情况下,把第3个数字变更为9,第4个数变更为10的话,就会变成1, 2, 9, 10, 5。此时,如果要求第2个数到第5个数的和的话,输出26就可以了。然后,在这个状态下,将第1个数字变更为-5,第三个数变更为5的话,会变成-5, 2, 5, 10, 5。,再然后,如果要求第1个数到第3个数的和的话,就是2。
请编写解决这种问题的程序。
输入
第一行给出整数的个数N。(1 ≤ N ≤ 100,000)
第二行给出操作的个数Q。(1 ≤ Q ≤ 200,000)
从第三行开始的Q行给出操作的信息。各操作以下面的形式实现。
· 0 x y:将第x个数变更为y。(1 ≤ x ≤ N, -100,000 ≤ y ≤ 100,000)
· 1 x y:求出从第x个数开始到第y个数为止的和。(1 ≤ x ≤ y ≤ N)。
输出
对于操作中以1开头的操作,将求得的值在一行上输出一个。此时要注意答案的范围有可能超过32-bit整数类型的范围。
案例输入
5
7
1 2 4
0 3 9
0 4 10
1 2 5
0 1 -5
0 3 5
1 1 3
案例输出
9
26
2
#include <stdio.h>
#define TMAX 131072
long long tree[TMAX * 2 + 3];
void set(int x, long long v) {
x+= TMAX;
tree[x] = v;
while (x > 1) {
x /= 2;
tree[x] = tree[x * 2] + tree[x * 2 + 1];
}
}
long long get(int l, int r) {
long long ret = 0;
l+= TMAX;
r+= TMAX;
while (l <= r) {
if (l % 2 == 1) {
ret += tree[l];
l ++;
}
if (r % 2 == 0) {
ret += tree[r];
r --;
}
l /= 2;
r /= 2;
}
return ret;
}
int main() {
int N;
scanf( "%d", &N );
for (int i = 1; i <= N; i ++) {
set(i, i);
}
int Q;
scanf( "%d", &Q );
while (Q --) {
int a, b, c;
scanf( "%d %d %d", &a, &b, &c );
if (a == 0) {
set(b, c);
} else {
printf( "%lld\n", get(b, c) );
}
}
return 0;
}