模板题出处 原理就大概如图所示,线段树的每个节点都是原数组的一段区间和,而叶子节点就是原数组对应 的值 建树代码: void build(int p,int lf,int rt){//建树 ans[p]=0; if(lf==rt) { ans[p]=A[lf]; return ; } int mid=(lf+rt)>>1; build(lson); build(rson); push_up(p); } 单点修改其实就是一直缩小被修改点所在区间直到区间与修改点重合。 单点修改代码: void update(int p,in 线段树是一种高效的数据结构,常用于处理动态区间查询和修改问题。在“线段树(单点查询+区间求和)无lazy标记”这个题目中,主要涉及到线段树的基本操作,包括如何构建线段树、单点修改以及区间求和。 1. **线段树的构建**: - `build`函数是线段树的初始化过程。它从根节点开始递归地向下构建线段树。每个节点`p`代表原数组的一个子区间,区间范围由`lf`和`rt`定义。如果`lf`等于`rt`,那么该节点是一个叶节点,其值`ans[p]`等于原数组的值`A[lf]`。否则,将区间分为两半,分别对左子树和右子树调用`build`,然后执行`push_up`操作来更新当前节点的值。 2. **单点修改**: - `update`函数用于单点修改。传入参数包括当前节点`p`,左边界`lf`,右边界`rt`,以及需要修改的位置`pos`和修改值`k`。如果`lf`等于`rt`,直接更新节点`p`的值;否则,根据`pos`的位置向左子树或右子树递归调用`update`,然后再次执行`push_up`以保持节点信息的正确性。 3. **区间求和**: - `sum`函数负责计算指定区间[l, r]的和。同样,从根节点开始,如果当前区间完全包含在[l, r]内,返回该节点的值。否则,如果目标区间覆盖了当前节点的左区间,递归查询左子树,如果覆盖了右区间,递归查询右子树。最后将两个子区间的结果相加得到整个区间的和。 4. **push_up**操作: - `push_up`函数是线段树的核心部分,它用于合并左右子节点的值到父节点。这里的实现方式是直接将左子树和右子树的值相加,赋值给父节点。这是因为线段树中的每个节点都存储了其子区间之和。 5. **完整代码**: - 提供的代码包含了线段树的初始化、单点修改、区间求和以及主函数等所有必要的部分。在主函数中,根据输入的指令`a`进行相应操作,如`a==1`表示单点修改,`a==2`表示区间求和。 6. **时间复杂度分析**: - 线段树的操作时间复杂度通常为O(logn),因为每次操作都是沿着树的高度进行的。在这个例子中,无论是单点修改还是区间求和,都需要在每一层进行一次操作,而树的高度是logn,因此总的时间复杂度是O(logn)。 线段树是一种强大的工具,尤其对于区间查询和修改的问题,它可以提供比朴素算法更优的时间复杂度。在这个无lazy标记的版本中,每次修改都会立即反映到所有受影响的节点,虽然这可能导致更多的更新操作,但在某些特定场景下,这种做法可能更直观和简单。
- 粉丝: 4
- 资源: 969
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助