区间内最大连续和查询(基于线段树的分治方法)
字数 1531 2025-10-26 19:15:22

区间内最大连续和查询(基于线段树的分治方法)

题目描述
给定一个整数数组,需要处理两种操作:

  1. 更新操作:修改数组中某个位置的值。
  2. 查询操作:查询某个区间内的最大连续子数组和(即该区间内连续元素的和的最大值)。

例如,数组 [1, -3, 2, 4, -1] 中,区间 [0, 4] 的最大连续和为 6(子数组 [2, 4] 的和)。要求设计一个高效算法,支持多次更新和查询操作。


解题过程

步骤1:理解问题难点
直接暴力计算每次查询需要 O(n²) 时间(枚举所有子数组),但若频繁查询和更新,效率极低。目标是将每次查询和更新优化到 O(log n) 时间,需借助线段树(Segment Tree)并维护特殊信息。

步骤2:线段树节点设计
每个节点代表一个区间 [l, r],存储以下四个值:

  • sum:区间内所有元素的和。
  • maxPrefix:区间内最大前缀和(从 l 开始的连续子数组和的最大值)。
  • maxSuffix:区间内最大后缀和(以 r 结尾的连续子数组和的最大值)。
  • maxSum:区间内最大连续子数组和。

例如,区间 [2, 4, -1] 的四个值分别为:

  • sum = 5
  • maxPrefix = 6(从首元素开始的最大和是 2+4=6
  • maxSuffix = 5(以末元素结束的最大和是 4+(-1)+2? 错误!正确计算:后缀包括自身,因此从右向左累加,-1+4+2=5
  • maxSum = 6(子数组 [2,4] 的和)。

步骤3:合并左右子区间
设左子节点 L 代表 [l, mid],右子节点 R 代表 [mid+1, r],父节点 P 的值计算如下:

  1. P.sum = L.sum + R.sum
  2. P.maxPrefix = max(L.maxPrefix, L.sum + R.maxPrefix)
    (最大前缀要么在左半部分,要么跨越左右两部分)
  3. P.maxSuffix = max(R.maxSuffix, R.sum + L.maxSuffix)
    (最大后缀要么在右半部分,要么跨越左右两部分)
  4. P.maxSum = max(L.maxSum, R.maxSum, L.maxSuffix + R.maxPrefix)
    (最大连续和可能完全在左半、完全在右半,或跨越中间边界)。

步骤4:建树与初始化

  • 叶子节点:区间长度为1时,sum = maxPrefix = maxSuffix = maxSum = 单元素值
  • 递归构建左右子树,然后按步骤3合并。
  • 时间复杂度:O(n)。

步骤5:更新操作

  • 从叶子节点开始更新值,向上递归更新父节点,每次按步骤3重新计算四个值。
  • 时间复杂度:O(log n)。

步骤6:查询操作

  • 查询区间可能覆盖多个节点,需递归合并部分区间。
  • 若查询区间完全覆盖当前节点,直接返回该节点的四个值。
  • 若查询区间部分覆盖左右子树,分别查询左右子树,得到 LR 后,按步骤3合并为一个节点返回。
  • 时间复杂度:O(log n)。

步骤7:示例验证
数组 [1, -3, 2, 4, -1] 查询 [0,4]

  • 递归合并所有叶子节点后,根节点的 maxSum=6(对应子数组 [2,4])。
  • 若更新索引2的值为 3,数组变为 [1,-3,3,4,-1],重新计算后 [0,4]maxSum=7(子数组 [3,4])。

总结
通过线段树维护每个区间的四个关键值,将动态区间最大连续和问题转化为 O(log n) 的更新和查询,适用于需要频繁操作的场景。

区间内最大连续和查询(基于线段树的分治方法) 题目描述 给定一个整数数组,需要处理两种操作: 更新操作 :修改数组中某个位置的值。 查询操作 :查询某个区间内的最大连续子数组和(即该区间内连续元素的和的最大值)。 例如,数组 [1, -3, 2, 4, -1] 中,区间 [0, 4] 的最大连续和为 6 (子数组 [2, 4] 的和)。要求设计一个高效算法,支持多次更新和查询操作。 解题过程 步骤1:理解问题难点 直接暴力计算每次查询需要 O(n²) 时间(枚举所有子数组),但若频繁查询和更新,效率极低。目标是将每次查询和更新优化到 O(log n) 时间,需借助线段树(Segment Tree)并维护特殊信息。 步骤2:线段树节点设计 每个节点代表一个区间 [l, r] ,存储以下四个值: sum :区间内所有元素的和。 maxPrefix :区间内最大前缀和(从 l 开始的连续子数组和的最大值)。 maxSuffix :区间内最大后缀和(以 r 结尾的连续子数组和的最大值)。 maxSum :区间内最大连续子数组和。 例如,区间 [2, 4, -1] 的四个值分别为: sum = 5 maxPrefix = 6 (从首元素开始的最大和是 2+4=6 ) maxSuffix = 5 (以末元素结束的最大和是 4+(-1)+2? 错误!正确计算:后缀包括自身,因此从右向左累加, -1+4+2=5 ) maxSum = 6 (子数组 [2,4] 的和)。 步骤3:合并左右子区间 设左子节点 L 代表 [l, mid] ,右子节点 R 代表 [mid+1, r] ,父节点 P 的值计算如下: P.sum = L.sum + R.sum P.maxPrefix = max(L.maxPrefix, L.sum + R.maxPrefix) (最大前缀要么在左半部分,要么跨越左右两部分) P.maxSuffix = max(R.maxSuffix, R.sum + L.maxSuffix) (最大后缀要么在右半部分,要么跨越左右两部分) P.maxSum = max(L.maxSum, R.maxSum, L.maxSuffix + R.maxPrefix) (最大连续和可能完全在左半、完全在右半,或跨越中间边界)。 步骤4:建树与初始化 叶子节点:区间长度为1时, sum = maxPrefix = maxSuffix = maxSum = 单元素值 。 递归构建左右子树,然后按步骤3合并。 时间复杂度:O(n)。 步骤5:更新操作 从叶子节点开始更新值,向上递归更新父节点,每次按步骤3重新计算四个值。 时间复杂度:O(log n)。 步骤6:查询操作 查询区间可能覆盖多个节点,需递归合并部分区间。 若查询区间完全覆盖当前节点,直接返回该节点的四个值。 若查询区间部分覆盖左右子树,分别查询左右子树,得到 L 和 R 后,按步骤3合并为一个节点返回。 时间复杂度:O(log n)。 步骤7:示例验证 数组 [1, -3, 2, 4, -1] 查询 [0,4] : 递归合并所有叶子节点后,根节点的 maxSum=6 (对应子数组 [2,4] )。 若更新索引2的值为 3 ,数组变为 [1,-3,3,4,-1] ,重新计算后 [0,4] 的 maxSum=7 (子数组 [3,4] )。 总结 通过线段树维护每个区间的四个关键值,将动态区间最大连续和问题转化为 O(log n) 的更新和查询,适用于需要频繁操作的场景。