树状数组/二叉索引树(Binary Indexed Tree):
A 数组就是原数组,C 数组则是树状数组。
通过观察可以发现:
1 2 3 4 5 6 7 8 9 10
| [1, 1] C1 = A1 [1, 2] C2 = A1 + A2 [3, 3] C3 = A3 [1, 4] C4 = A1 + A2 + A3 + A4 [5, 5] C5 = A5 [5, 6] C6 = A5 + A6 [7, 7] C7 = A7 [1, 8] C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
C[i] 管理的区间:[i - bitLow(i) + 1, i]
|
它的查询和修改的时间复杂度都是 O(logN),空间复杂度则为 O(N),这是因为树状数组通过将线性结构转化成树状结构,从而进行跳跃式扫描。
通常使用在高效的计算数列的前缀和,区间和。
模版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| class BinaryIndexedTree { int length; int[] tree;
BinaryIndexedTree(int length) { this.length = length; tree = new int[length + 1]; }
void put(int index, int value) { while (index <= length) { tree[index] += value; index += lowBit(index); } }
int get(int index) { int sum = tree[index]; int z = index - lowBit(index); index--; while (index != z) { sum -= tree[index]; index -= lowBit(index); } return sum; }
static int lowBit(int k) { return k & -k; }
int sum(int index) { int sum = 0; while (index > 0) { sum += tree[index]; index -= lowBit(index); } return sum; }
int sum(int start, int end) { return sum(end) - sum(start - 1); } }
|