这是一道树状数组的入门题啦.
学习树状数组的时候多拿笔算算就比较好理解为什么算法的查询和修改都是logn的了.
c[i] = a[i - 2^k + 1] + a[i - 2^k + 2] + ... + a[i], 其中k为i的二进制表示最后几位零的个数, 如i=8, 那么1000三个0咯, 那么c[8] = a[1]+a[2]+...+a[8]啦.
还有哦, i的二进制表示末尾0的个数k还表示了c[i]所包含的范围哦.
比如吧, c[5], 5的二进制数是101吧, 最后没有0哦, 那么它只能包含a[5]咯, c[6]呢? 6的二进制是110哦, 所以呢, 它能包含a[5]和a[6]哦
还有呢, i包含的最大的2的幂的因子也能表示i所能包含的个数哦, 如i=5吧, 5没有包含2^x的因子吧, 所以呢, 它只能包含a[5]咯
i=4呢. 它有2^2嘛, 所以它能包含4个, i=6, 它只有2^1, 所以它只能包含a[5]和a[6]咯
所有基数都是没有2的幂的因子吧, 所以基数只能包含一个咯. 即c[1]=a[1], c[3]=a[3]...
#include <stdio.h>
#include <string.h>
#define MAX 50005
int a[MAX];
int c[MAX];
int n;
int lowbit(int index) {
return index & (-index);
}
int query(int index) {
int result = 0;
while (index > 0) {
result += c[index];
index -= lowbit(index);
}
return result;
}
void add(int index, int delta) {
while (index <= n) {
c[index] += delta;
index += lowbit(index);
}
}
void sub(int index, int delta) {
while (index <= n) {
c[index] -= delta;
index += lowbit(index);
}
}
int main() {
int T, t;
int i, j;
int lb;
char q[10];
int x, y;
while (scanf("%d", &T) == 1) {
t = 0;
while (T--) {
memset(a, 0, sizeof(a));
memset(c, 0, sizeof(c));
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for (i = 1; i <= n; i++) {
lb = lowbit(i);
for (j = i - lb + 1; j <= i; j++) {
c[i] += a[j];
}
}
printf("%d", query(5) - query(4));
t++;
while (true) {
scanf("%s", q);
if (!strcmp(q, "End")) {
break ;
}
scanf("%d%d", &x, &y);
if (!strcmp(q, "Query")) {
// printf("%d\n", query(y) - query(x) + query(x - 1));
printf("%d\n", query(y) - query(x) + a[x]);
} else if (!strcmp(q, "Add")) {
add(x, y);
a[x] += y;
} else {
sub(x, y);
a[x] -= y;
}
}
}
}
return 0;
}