线段树
线段树的功能比树状数组更加强大,主要有以下四种功能:
(1)pushup:用子节点信息更新当前节点信息
(2)build:在一段区间上初始化线段树
(3)modify:修改
(4)query:查询
用一维数组存储线段树,对于线段树的任意一个节点tree[i]:
它的父节点:x >> 1
它的左儿子:x << 1
它的右儿子:x << 1 | 1
相关阅读
树状数组节点信息
区间左右边界,以及区间和
struct Node{
int L, R, sum;
}tree[4 * N];
pushUp
用子节点信息更新当前节点信息
void pushUp(int index){
tree[index].sum = tree[index << 1].sum + tree[index << 1 1].sum;
}
build
在一段区间上初始化线段树
void build(int root, int L, int R){
if(L == R) tree[root] = {L, R, s[R]};
else{
tree[root] = {L, R};
int mid = L + (R - L >> 1);
build(root << 1, L, mid);
build(root << 1 | 1, mid+1, R);
pushUp(root);
}
}
modify
修改
void modify(int root, int index, int v){
if(tree[root].L == tree[root].R) tree[root].sum += v;
else{
int mid = tree[root].L + ((tree[root].R - tree[root].L) >> 1);
if(index <= mid) modify(root << 1, index, v);
else modify(root << 1 | 1, index, v);
pushUp(root);
}
}
query
查询
int s[N];
int query(int root, int L, int R){
if(tree[root].L >= L && tree[root].R <= R) return tree[root].sum;
int mid = tree[root].L + ((tree[root].R - tree[root].L) >> 1);
int sum = 0;
if(L <= mid) sum += query(root << 1, L, R);
if(R > mid) sum += query(root << 1 | 1, L, R);
return sum;
}