树状数组是线段树的一种特殊情况,对于特殊情况用树状数组会更简单。
数组数组详细:http://blog.csdn.net/gladyoucame/article/details/11881399
此题线段树的解法: http://blog.csdn.net/gladyoucame/article/details/9293357
定义一个函数Lowbit(Int):Int,返回对参数转为二进制后,将最后一个1进位的结果.
这段代码可以简单的理解为是树状数组向前或向后衍生是用的。
向后主要是为了找到目前节点的父节点,比如要将C[4]+1,那么4+(4&(-4))=8,C[8]+1,8+(8&(-8))=16,
C[16]+1。
向前主要是为了求前缀和,比如要求A[1]+...+A[12]。那么,C[12]=A[9]+...+A[12];然后12-12&(-12)=8,
C[8]=A[1]+...+A[8]。
#include <iostream>
#include <stdio.h>
using namespace std;
const int MAX = 50000;
//
#define lowbit(x) ((x)&(-x)) //或 x and (x or (x - 1));
int com[MAX + 1], N, T;
//修改位置pos处的值, 增量为va
void modify(int pos, int val) {
while (pos <= N) {
com[pos] += val;
pos = pos + lowbit(pos);
}
}
//查询
int quy(int x) {
int sum = 0;
while (x > 0) {
sum = sum + com[x];
x = x - lowbit(x);
}
return sum;
}
int main()
{
while (scanf("%d", &T) != EOF) {
int ca = 1, x, y;
while (T--) {
printf("Case %d:\n", ca++);
scanf("%d", &N);
for (int i = 0; i <= N; ++i)
com[i] = 0;
for (int i = 1; i <= N; ++i) {
scanf("%d", &x);
modify(i, x);
}
char ask[10];
while (scanf("%s", ask), ask[0] != 'E') {
scanf("%d%d", &x, &y);
switch (ask[0]) {
case 'A':
modify(x, y);
break;
case 'S':
modify(x, -y); //值减少,所以为负
break;
case 'Q':
printf("%d\n", quy(y) - quy(x - 1));
break;
}
}
}
}
return 0;
}