侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1825 篇文章
  • 累计收到 0 条评论

使用线段树实现区间求和

2025-12-12 / 0 评论 / 4 阅读

题目

使用线段树实现区间求和

信息

  • 类型:问答
  • 难度:⭐

考点

线段树基本概念,线段树构建,单点更新,区间查询

快速回答

线段树是一种用于高效处理区间查询的二叉树结构。本题要求实现:

  • 构建线段树:递归地将数组划分为左右子树
  • 单点更新:递归更新叶子节点并回溯更新父节点
  • 区间查询:递归合并子区间的查询结果

核心公式:
父节点索引 = (当前索引 * 2) + 1(左子节点)
父节点索引 = (当前索引 * 2) + 2(右子节点)

解析

原理说明

线段树是一种二叉树结构,每个节点存储一个区间的聚合信息(如区间和)。对于长度为 n 的数组:

  • 叶子节点:存储单个元素值
  • 非叶子节点:存储子区间的合并值(如左右子节点之和)
  • 树高度:O(log n),支持 O(log n) 的更新和查询

代码示例(Python)

class SegmentTree:
    def __init__(self, data):
        self.n = len(data)
        self.size = 4 * self.n  # 保守估计空间
        self.tree = [0] * self.size
        self._build(data, 0, 0, self.n-1)

    # 构建线段树
    def _build(self, data, idx, left, right):
        if left == right:
            self.tree[idx] = data[left]
            return
        mid = (left + right) // 2
        self._build(data, 2*idx+1, left, mid)    # 左子树
        self._build(data, 2*idx+2, mid+1, right) # 右子树
        self.tree[idx] = self.tree[2*idx+1] + self.tree[2*idx+2]

    # 单点更新
    def update(self, pos, value, idx=0, left=0, right=None):
        if right is None: right = self.n-1
        if left == right:
            self.tree[idx] = value
            return
        mid = (left + right) // 2
        if pos <= mid:
            self.update(pos, value, 2*idx+1, left, mid)
        else:
            self.update(pos, value, 2*idx+2, mid+1, right)
        self.tree[idx] = self.tree[2*idx+1] + self.tree[2*idx+2]

    # 区间查询
    def query(self, ql, qr, idx=0, left=0, right=None):
        if right is None: right = self.n-1
        if qr < left or ql > right:  # 区间无重叠
            return 0
        if ql <= left and qr >= right:  # 完全包含
            return self.tree[idx]
        mid = (left + right) // 2
        left_sum = self.query(ql, qr, 2*idx+1, left, mid)
        right_sum = self.query(ql, qr, 2*idx+2, mid+1, right)
        return left_sum + right_sum

# 使用示例
arr = [1, 3, 5, 7, 9]
sg_tree = SegmentTree(arr)
print(sg_tree.query(1, 3))  # 输出 15 (3+5+7)
sg_tree.update(2, 10)       # 将位置2的元素更新为10
print(sg_tree.query(1, 3))  # 输出 20 (3+10+7)

最佳实践

  • 空间分配:使用 4*n 的保守空间避免溢出
  • 递归终止条件:区间长度为1时到达叶子节点
  • 区间划分:使用 mid = (left + right) // 2 保证平衡
  • 查询优化:当当前区间完全包含在查询区间时直接返回

常见错误

  • 索引错误:混淆左右子树索引(左:2*i+1,右:2*i+2)
  • 区间不匹配:构建/查询时未正确传递 [left, right] 边界
  • 更新遗漏:修改叶子节点后未回溯更新父节点
  • 空间不足:数组开太小导致越界(最小需 4*n 空间)

扩展知识

  • 变种应用:区间最小值(Min Segment Tree)、区间最大值
  • 惰性传播:高效处理区间更新的延迟更新技术
  • 动态线段树:支持动态插入/删除元素
  • 替代结构:树状数组(Binary Indexed Tree)在单点更新+区间求和场景更简洁