树状数组是线段树的一种特殊情况,对于特殊情况用树状数组会更简单。
数组数组详细: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; }