> 文章列表 > 2023/4/10总结

2023/4/10总结

2023/4/10总结

线段

线段树是一种二叉树,通俗易懂的来说就是对于一个线段,我们会用一个二叉树来表示。线段树是一种工具,她能把对区间(线段)的修改与维护从0(N)的时间复杂度变成0(logN)。

如图:

在这里插入图片描述

 如上图,我们可以得到一个性质:节点i的权值=她的左孩子的权值+她的右孩子的权值。

 我们知道,一颗从1开始编号的二叉树,节点i的左孩子和右孩子的编号分别是2*i和2*i+1.

 当我们建立一颗线段树时,我们设一个结构体,她一般需要包含三个元素,一个左子树下标,一个右子树下标,还有一个表示这个节点表示的线段和。

建树代码如下:

void build(int i,int l,int r)
tree[i].l=l;tree[i].r=r;
if(l==r)//如果这个节点是叶子节点
{
tree[i].sum=l;
return ;
}
int mid=(l+r)>>1;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tree[i].sum=tree[i*2].sum+tree[[i*2+1].sum;
}

 需要注意的是我们在构建一颗线段树时,可能需要开好几倍的内存去存储。 

前面说了,线段树的主要功能是对区间进行维护和修改,既然要进行以上的两种操作那肯定要先对这棵树进行查询,在这里我先给出查找某一段区间和的查询方法:

1.查询从根节点开始,依次向下查询

2.如果查询到的这个区间完全包括在要查询的目标区间里面,那么直接返回这个区间的值。

3.如果这个区间的左儿子和要查询的左儿子有交集,那么搜索左儿子。

4.如果这个区间的右儿子和要查询的左儿子有交集,那么搜索右儿子。

5.将搜索到的值依次返回即可。

    int search(int i,int l,int r){if(tree[i].l>=l && tree[i].r<=r) return tree[i].sum;if(tree[i].r<l || tree[i].l>r)  return 0; int s=0;if(tree[i*2].r>=l)  s+=search(i*2,l,r); if(tree[i*2+1].l<=r)  s+=search(i*2+1,l,r); return s;
}

今天只大概了解了线段树的一部分,剩下的明天再深入学习。 

https://blog.csdn.net/weixin_65829986/article/details/130025091 

https://blog.csdn.net/weixin_65829986/article/details/130024647