1.区间树定义
- 区间树:区间树是一个区间划分成一些单元区间(即单个数据),每个单元区间对应一个叶节点,非叶节点表示其所代表的子树对应的子区间。区间树中,每个节点的子节点分别表示它的左右半区间。对于每一个非叶节点 ,设其对应区间为[a, b],它的左子树表示的区间为[a, (a+b)/2], 右子树表示的区间为[(a+b)/2+1, b]
类的各种成员:
struct Node{
int l, r;
int val;
Node() :l(-1), r(-1), val(-1){}
};
2.区间树操作
2.1 区间树的建立
void build(int node, int l, int r) {
itv[node].l = l;
itv[node].r = r;
if (l == r) {
itv[node].val = arr[l];
return ;
}
build(2 * node, l, l + (r - l) / 2);
build(2 * node + 1, l + (r - l) / 2 + 1, r);
itv[node].val = itv[2 * node].val + itv[2 * node + 1].val;
}
2.2 区间树的查询
int query(int node, int l, int r) {
if (itv[node].l > r || itv[node].r < l) {
return -1;
}
if (l <= itv[node].l && itv[node].r <= r) {
return itv[node].val;
}
int resl = query(2 * node, l ,r);
int resr = query(2 * node + 1, l ,r);
if (resl == -1) return resr;
if (res r== -1) return resl;
return resl + resr;
}
2.3 区间树的某个节点进行更新
void update(int node,i nt key, int value) {
if (itv[node].l == itv[node].r) {
itv[node].val = value;
} else {
int mid = itv[node].l + (itv[node].r - itv[node].l) / 2;
if (key <= mid) {
update(2 * node, key, value);
} else {
update(2 * node + 1, key, value);
}
itv[node].val = itv[2 * node].val + itv[2 * node + 1].val;
}
}
2.4 区间树的对一定范围的区间的数值进行修改
void down(int node) {
itv[2 * node].k += itv[node].k;
itv[2 * node+1].k += itv[node].k;
itv[2 * node].val += itv[2*node].k * (itv[2 * node].r-itv[2 * node].l + 1);
itv[2 *node+1].val += itv[2 * node + 1].k * (itv[2 * node + 1].r-itv[2 * node + 1].l + 1);
itv[node].k = 0;
}
void add(int node, int l, int r, int value){
if (l <= itv[node].l && itv[node].r <= r) {
itv[node].val += (itv[node].r - itv[node].l + 1) * value;
itv[node].k += value;
} else {
if (itv[node].k > 0) {
down(node);
}
int mid = itv[node].l + (itv[node].r - itv[node].l) / 2;
if (r <= mid) {
add(2 * node, l, r, value);
} else if(l > mid) {
add(2 *node + 1, l, r, value);
} else {
add(2 * node, l, r, value);
add(2 * node + 1, l, r, value);
}
itv[node].val=itv[2*node].val+itv[2*node+1].val;
}