树状数组
1. 什么是树状数组?
假设C [i]表示这个数据结构的第i个元素, A [i]表示第i数的数值。
C [i] = A [i] ( i 为奇数)
C [i] = A [k] + .. + A [i]; (k 等于 i的二进制最后一位1去掉 + 1, i为偶数)
看图,
2. 想法
感觉这是某个理论的衍生物,或者是多个理论的杂交物。
3. 应用
经常用在对紧挨着的大量的数字进行相加, 而且其中会修改某一位数字, 其时间复杂度 logn.
4. 我用它解决这个问题(附上代码)
- 描述
-
南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。
小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。
南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。
- 输入
- 只有一组测试数据
第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示指令的条数。(1<M<100000)
随后的一行是N个整数,ai表示第i号士兵杀敌数目。(0<=ai<=100)
随后的M行每行是一条指令,这条指令包含了一个字符串和两个整数,首先是一个字符串,如果是字符串QUERY则表示南将军进行了查询操作,后面的两个整数 m,n,表示查询的起始与终止士兵编号;如果是字符串ADD则后面跟的两个整数I,A(1<=I<=N,1<=A<=100), 表示第I个士兵新增杀敌数为A.
- 输出
- 对于每次查询,输出一个整数R表示第m号士兵到第n号士兵的总杀敌数,每组输出占一行
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SIZE 1000000 #define CMD_MAX_SIZE 10 int c [MAX_SIZE + 1] = {0}; //树状数组 int a [MAX_SIZE + 1] = {0}; int main(void) { int N,M; int temp; int sum = 0; int i, j; char cmdStr [CMD_MAX_SIZE]; int m, n; int GetLast(int value); int GetSum(int n); void AddIt(int index, int value, int maxSize); memset((unsigned char *)c, 0, (MAX_SIZE + 1) * sizeof(int)); //清零 memset((unsigned char *)a, 0, (MAX_SIZE + 1) * sizeof(int)); scanf("%d%d",&N,&M); for(i = 1; i <= N; i ++) //初始化 { scanf("%d", &a [i]); if(i % 2 == 0) { for(j = i - GetLast(i) + 1; j <= i; j ++) { c [i] += a [j]; } } else { c [i] = a [i]; } } while(M --) { fscanf(stdin, "%s %d %d", cmdStr, &m, &n); //或者i和addNum if(!strcmp(cmdStr, "QUERY")) { fprintf(stdout, "%d\n", GetSum(n) - GetSum(m - 1) ); } else if(!strcmp(cmdStr, "ADD")) { AddIt(m, n, N); } else { exit(EXIT_FAILURE); } } return 1; } /* * 获取整数的二进制形式左数最后一个1 * value -- 指定整数 * 返回结果。 */ int GetLast(int value) { return value & (-value); } /* * 获取前n个数的和 * n -- 表示前n个数 * 返回它们的和。 */ int GetSum(int n) { int sum = 0; while(n > 0) { sum += c [n]; n -= GetLast(n); } return sum; } /* * 给某个元素加值 * index -- 指定元素的序号 * value -- 加的数值 * maxSize -- 树状数组的上界 */ void AddIt(int index, int value, int maxSize) { int GetLast(int value); while(index <= maxSize) { c [index] += value; index += GetLast(index); } }