所谓线段树, 就是一种支持在线更新和查询的数据结构, 建树的时间复杂度为O(nlogn), 而大多数情况能保证每次查询的复杂度为O(logn), 搞笑快速。
建树:
大概就是这样, 每个区间都有一个父节点, 设父节点下标为rt, 区间为[l, r], rt存的是该区间内的信息;
当 l == r时, rt代表下标为l的单点信息。rt的左孩子下标为rt << 1, 右孩子为rt << 1|1;
左孩子区间:[l, (l + r) >> 1]
右孩子区间:[((l + r) >> 1) + 1, r]
所以, 大致用到的空间为2 *n - 1(n位数据量), 但是一般开到4倍的空间比较稳。
建树的代码:
void pushUp(int rt) { //用孩子更新父节点信息
//code
}
void build(int rt, int l, int r) { //rt为当前节点, [l , r]为区间
if (l == r) {
//code //找到单点初始化,返回
return;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid); //未找到单点递归左孩子, 右孩子建树
build(rt << 1 | 1, mid + 1, r);
pushUp(rt);
}
#define mid ((l + r) >> 1)
#define ls rt << 1, l, mid
#define rs rt << 1|1, mid + 1, r
void pushUp(int rt) { //用孩子更新父节点信息
//code
}
void build(int rt, int l, int r) { //rt为当前节点, [l , r]为区间
if (l == r) {
//code //找到单点初始化,返回
return;
}
build(ls); //未找到单点递归左孩子, 右孩子建树
build(rs);
pushUp(rt);
}
更新和查询, 和建树类似, 找到区间, 在更新, pushUp;
有待更新....先去上课