#define lowbit(i) (-i & i) // 二进制数字最低位'1'和其后'0'组成的数字
template<typename T>
class BinaryIndexedTree {
public:
BinaryIndexedTree(const vector<T>& arr) :LEN(arr.size()) {
ori = arr;
ori.insert(ori.begin(), INT_MAX);
BuildBIT(arr);
}
/*
* 构建树状数组,index 从1开始, 输入数组index 从 0 开始,利用update 操作完成
*/
void BuildBIT(const vector<T> &arr) {
idx.resize(LEN + 1, INT_MAX);
for (int i = 1; i <= LEN; ++i) {
idx[i] = arr[i - 1];
for (int j = i - 1; j > i - lowbit(i); j -= lowbit(j)) {
idx[i] = min(idx[i], idx[j]);
}
/* 另外一种写法
* for(int j=1;j<lowbit(i); j<<=1){
* idx[i]=min(idx[i],idx[i-j]);
* }
*/
}
}
int Query(int start, int end) {
int ret = ori[end];
start++; // 索引重映射
end++;
while (end >= start) {// idx[end]覆盖的左边界小于等于start点
if (start <= end - lowbit(end) + 1) {
ret = min(ret, idx[end]);
end -= lowbit(end); // 兄弟结点
}
else { // idx[end]覆盖的左边界大于start点
ret = min(ret, ori[end--]);
}
}
return ret;
}
void modify(int id, const int val) {
ori[++id] = val;// ++id, 索引重映射
for (int index = id; index <= LEN; index += lowbit(index)) {//向上遍历,找父亲结点
idx[index] = ori[index];
for (int j = index - 1; j > index - lowbit(index); j -= lowbit(j)) {//遍历孩子结点
idx[index] = min(idx[index], idx[j]);
}
}
}
private:
vector<T> idx;
vector<T> ori; //original array
const int LEN;
};
树状数组求区间最值
最新推荐文章于 2022-05-10 11:21:16 发布