1.统计区间 sum
2.修改某个数组值
#define lowbit(i) ( -i & i) // 二进制数字最低位'1'和其后'0'组成的数字
template<typename T>
class BinaryIndexedTree {
public:
BinaryIndexedTree(const vector<T>& arr) :LEN(arr.size()){
BuildBIT(arr);
}
~BinaryIndexedTree() {
}
/*
* 构建树状数组,index 从1开始, 输入数组index 从 0 开始,利用update 操作完成
*/
void BuildBIT(const vector<T> &arr) {
bit.resize(LEN+ 1, 0);
for (auto i = 1; i <= LEN; ++i)
update(i, arr[i - 1]);
}
/*
* 直观上是,应该更新 arr[i]
* 实际上,更新树状数组, val为增量或减量,而不是更新后的值
*/
void update(int i, int val) {
while (i <= LEN) {
bit[i] += val;
i += lowbit(i); // 类似父结点,从而更新父亲结点
}
}
/*
* 累加arr[1 .. index] 的值 并且返回
*/
T sum( int index) {
T ret = 0;
while (index > 0) {
ret += bit[index];
index -= lowbit(index); //类似兄弟结点
}
return ret;
}
/*
* 累加arr[index_i + 1 .. index_j] 的值 并且返回
*/
T sum( int index_i, int index_j) {
return sum(index_j) - sum(index_i);
}
/*
* 返回 arr[index]
* 三种方法:
* 1. 增加一个arr数组
* 2. 利用 sum(index - 1, index);
* 3. 当前方法
*/
T getElem(int index) {
T ret = bit[index];
unsigned sibling = index - lowbit(index);
index--;
while (index != sibling) {
ret -= bit[index];
index -= lowbit(index); //类似兄弟结点
}
return ret;
}
private:
vector<T> bit;
const unsigned LEN;
};
树状数组结构:
1.黑色代表原有数组,红色代表树状数组
2. 有同一父结点的结点为兄弟结点