线段树的入门
首先我们应该需要明白线段树可以解决的问题,如 求解数组区间之和,更新区间等
如果使用暴力的方法会超时,这样就引入了线段树这一数据结构线段树的本质是一颗平衡二叉树
线段树的基本性质如下:父亲的区间是[a,b] (c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树需要的空间为数组大小的四倍。
以1到10的区间举例,构造的线段树如下
线段树算法包括的主要的函数有三个(和树状数组的一样哎
build(建树函数), update(更新函数), query(查询区间和函数)
先定义下树的结构体
struct node //这就是一棵树
{
int left, right; // 树的子树
int sum; //树的和
}tree[N];
build函数
void build(int l,int r,int step)
{
tree[step].left = l;
tree[step].right = r;
if(l == r) return ; //书已经到了叶子节点。该返回了
int mid = (l+r) >> 1; //二分建树
build(l,mid,step<<1); //递归建立左子树
build(mid+1,r,step<<1|1);//递归建立右子树
}
update函数
void update(int l, int r, int value, int step)
{
if(tree[step].left == tree[step].right) //一直更新到叶子点
return ;
int mid = (tree[step].left+tree[step].right) >> 1;
//如果所要更新的点的右端小于mid或左端点大于mid,则直接更新l到r的值
if(r <= mid) update(l,r,value,step<<1);
else if(l > mid) update(l,r,value,step<<1|1);
//如果要更新的点在mid两边,则两边分别更新
else {
update(l,mid,value,step<<1);
update(mid+1,r,value,step<<1|1);
}
}
query函数
int query(int l, int r,int step)
{
//找到叶子返回值
if(l==tree[step].left && r==tree[step].right) return tree[step].sum;
int mid = (tree[step].left+tree[step].right) >> 1;
//和更新类似
if(r <= mid) return query(l,r,step<<1);
if(l > mid) return query(l,r,step<<1|1);
else
return query(l,mid,step<<1)+query(mid+1,r,step<<1|1) ;
}
这三个函数就是线段树的精华了2333
帮助大家理解写几道线段树的模板题更好的理解模板
经典入门题HDU1166-敌兵布阵