Binary Indexed Tree,从字面上来看是数,但是其实是数组。这个数组主要用来数组求和。例如对于某个数组[1,2,3,4,5],其树状数组的定义是:c[i]=a[i-2^r+1]+...+a[i],其中r是i二进制中最后一个1的长度。
2^r的确定是i & (i ^ (i - 1))。
树状数组主要有一下应用:求解树状数组,求前n项的和,当某个位置发生变化更新树状数组,获取某特定位置的值。
其代码如下:
#include <iostream>
#include <vector>
using namespace std;
int getIndex(int x) {
return x & (x ^ (x - 1));
}
//构建树状数组
void buildTree(vector<int> &nums, vector<int> &tree){
for(int i = 0;i < nums.size();i++) {
int pos = i + 1;
int index = getIndex(pos);
for(int j = pos - index; j < pos;j++) {
tree[i] += nums[j];
}
}
}
//求前n项的和
int getSum (vector<int> &trees, int pos) {
int sum = 0;
while(pos >= 0) {
sum += trees[pos];
pos -= (getIndex(pos + 1));
}
return sum;
}
//某个位置的数值发生变化,val是差值
void update(vector<int> &trees, int pos, int val) {
while (pos < trees.size()) {
trees[pos] += val;
pos += getIndex(pos + 1);
}
}
//获取特定位置的值
int getPosNum(vector<int> &trees, int pos) {
if (pos == 0) {
return trees[pos];
}
int sum = trees[pos];
int z = pos - getIndex(pos + 1);
pos -= 1;
while (pos != z) {
sum -= trees[pos];
pos -= getIndex(pos + 1);
}
return sum;
}
int main(){
int a[10] = {5,12,-3,13,4,1,5,9,2,7};
vector<int> nums(a, a + 10);
vector<int> tree(10, 0);
buildTree(nums,tree);
// int c = getSum(tree,3);
// cout << c << endl;
// update(tree,2,2);
// for (int i = 0;i < 10;i++) {
// cout << tree[i] << endl;
// }
int c = getPosNum(tree,2);
cout << c << endl;
}