线段树的区间查询与更新
字数 933 2025-11-15 11:21:24
线段树的区间查询与更新
知识点描述
线段树(Segment Tree)是一种二叉树结构,用于高效处理数组的区间查询(如区间和、最小值)和区间更新操作。它将每个区间划分为若干子区间进行预处理,使得查询和更新的时间复杂度均为O(log n)。本知识点将详细讲解线段树的构建、区间查询和区间更新原理。
一、线段树的基本结构
- 存储方式:线段树使用数组模拟完全二叉树,每个节点存储一个区间的统计值(如区间和)
- 对于长度为n的原始数组,线段树需要4n大小的存储空间(保证最坏情况下不会越界)
- 节点关系(下标从1开始计数):
- 根节点下标为1
- 节点i的左子节点下标为2*i
- 节点i的右子节点下标为2*i+1
二、线段树的构建过程
以区间和查询为例,构建步骤:
- 递归划分区间:从根节点开始,将区间不断二分
- 叶子节点处理:当区间长度为1时,直接存储数组元素值
- 合并子节点:非叶子节点的值=左子节点值+右子节点值
示例代码框架:
def build_tree(tree, data, node, left, right):
if left == right: # 叶子节点
tree[node] = data[left]
else:
mid = (left + right) // 2
build_tree(tree, data, 2*node, left, mid) # 递归构建左子树
build_tree(tree, data, 2*node+1, mid+1, right) # 递归构建右子树
tree[node] = tree[2*node] + tree[2*node+1] # 合并子节点值
三、区间查询操作
查询区间[ql, qr]的求和:
- 从根节点开始递归查询
- 若当前节点区间完全包含在查询区间内,直接返回节点值
- 若与查询区间部分重叠,则分别查询左右子树
关键步骤:
- 计算中间位置mid = (left+right)//2
- 查询左子树:当ql ≤ mid时
- 查询右子树:当qr ≥ mid+1时
示例代码:
def query_tree(tree, node, left, right, ql, qr):
if ql <= left and right <= qr: # 完全包含
return tree[node]
mid = (left + right) // 2
res = 0
if ql <= mid: # 查询左子树
res += query_tree(tree, 2*node, left, mid, ql, qr)
if qr > mid: # 查询右子树
res += query_tree(tree, 2*node+1, mid+1, right, ql, qr)
return res
四、区间更新操作
单点更新可直接递归修改,区间更新需引入懒标记(Lazy Propagation)优化:
- 懒标记原理:延迟更新操作,只有在需要时才将标记下推
- 更新步骤:
a. 若当前区间完全包含在更新区间内,更新节点值并设置懒标记
b. 否则先将懒标记下推给子节点,再递归更新左右子树
懒标记更新示例(区间加值):
def update_tree(tree, lazy, node, left, right, ul, ur, val):
if ul <= left and right <= ur: # 完全包含
tree[node] += (right-left+1) * val
lazy[node] += val
return
# 下推懒标记
mid = (left+right)//2
if lazy[node] != 0:
tree[2*node] += (mid-left+1)*lazy[node]
tree[2*node+1] += (right-mid)*lazy[node]
lazy[2*node] += lazy[node]
lazy[2*node+1] += lazy[node]
lazy[node] = 0
# 递归更新子树
if ul <= mid:
update_tree(tree, lazy, 2*node, left, mid, ul, ur, val)
if ur > mid:
update_tree(tree, lazy, 2*node+1, mid+1, right, ul, ur, val)
tree[node] = tree[2*node] + tree[2*node+1] # 更新当前节点
五、时间复杂度分析
- 构建时间复杂度:O(n)(每个节点处理一次)
- 查询/更新时间复杂度:O(log n)(树高为log n)
- 空间复杂度:O(n)(使用4n大小的数组)
六、应用场景扩展
- 支持区间最值查询(将求和改为求最值)
- 多维线段树处理多维数据
- 动态开点线段树处理稀疏区间
通过以上步骤,线段树将区间操作转化为对数级别的操作,是处理区间问题的核心数据结构。掌握懒标记技巧是高效实现区间更新的关键。