线段树的定义:
首先,线段树是一棵完全二叉树。它的特点是:每个结点表示的是一个线段,或者说是一个区间。事实上,一棵线段树的根结点表示的是“整体”区间,而它的左右子树也是一棵线段树,分别表示区间的左半边和右半边。树中的每个结点表示一个区间[a,b]。每一个叶子结点表示一个单位区间。对于每一个非叶结点所表示的结点[a,b],其左孩子表示的区间为[a,(a+b)/2],右孩子表示的区间为[(a+b)/2,b]。 用T(a, b)表示一棵线段树,参数a,b表示区间[a,b],其中b-a称为区间的长度,记为L。如下图
实际上,用语言描述有点麻烦,具体可以看B站视频,还有一些其他人的介绍:线段树
话不多说,上代码:
class SegTree {
vector<int> nums;
int numsLen;
vector<int> trees;
void buildTree(int index, int left, int right) {
// index为当前结点在二叉树中的标号,left right 对应nums中的范围,即当前结点index所管理的范围为nums[left, right]
if (left >= right) {
trees[index] = nums[left];
return;
}
int mid = (left + right) / 2;
int node_left = index * 2 + 1; // 左结点的下标
int node_right = index * 2 + 2; // 右结点的下标
buildTree(node_left, left, mid);
buildTree(node_right, mid + 1, right);
trees[index] = trees[node_left] + trees[node_right]; // 改变当前结点的值,分治思想
}
// 查找区间