LeetCode 题解工作台
不包含相邻元素的子序列的最大和
给你一个整数数组 nums 和一个二维数组 queries ,其中 queries[i] = [pos i , x i ] 。 对于每个查询 i ,首先将 nums[pos i ] 设置为 x i ,然后计算查询 i 的答案,该答案为 nums 中 不包含相邻元素 的 子序列 的 最大 和。 返回所…
4
题型
5
代码语言
3
相关题
当前训练重点
困难 · 状态·转移·动态规划
答案摘要
根据题目描述,我们需要进行多次单点修改和区间查询,这种场景下,我们考虑使用线段树来解决。 首先,我们定义一个 类,用于存储线段树的节点信息,包括左右端点 和 ,以及四个状态值 , , 和 。其中:
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你一个整数数组 nums 和一个二维数组 queries,其中 queries[i] = [posi, xi]。
对于每个查询 i,首先将 nums[posi] 设置为 xi,然后计算查询 i 的答案,该答案为 nums 中 不包含相邻元素 的 子序列 的 最大 和。
返回所有查询的答案之和。
由于最终答案可能非常大,返回其对 109 + 7 取余 的结果。
子序列 是指从另一个数组中删除一些或不删除元素而不改变剩余元素顺序得到的数组。
示例 1:
输入:nums = [3,5,9], queries = [[1,-2],[0,-3]]
输出:21
解释:
执行第 1 个查询后,nums = [3,-2,9],不包含相邻元素的子序列的最大和为 3 + 9 = 12。
执行第 2 个查询后,nums = [-3,-2,9],不包含相邻元素的子序列的最大和为 9 。
示例 2:
输入:nums = [0,-1], queries = [[0,-5]]
输出:0
解释:
执行第 1 个查询后,nums = [-5,-1],不包含相邻元素的子序列的最大和为 0(选择空子序列)。
提示:
1 <= nums.length <= 5 * 104-105 <= nums[i] <= 1051 <= queries.length <= 5 * 104queries[i] == [posi, xi]0 <= posi <= nums.length - 1-105 <= xi <= 105
解题思路
方法一:线段树
根据题目描述,我们需要进行多次单点修改和区间查询,这种场景下,我们考虑使用线段树来解决。
首先,我们定义一个 类,用于存储线段树的节点信息,包括左右端点 和 ,以及四个状态值 , , 和 。其中:
- 表示不包含当前节点左右端点的子序列的最大和;
- 表示不包含当前节点左端点的子序列的最大和;
- 表示不包含当前节点右端点的子序列的最大和;
- 表示包含当前节点左右端点的子序列的最大和。
接着,我们定义一个 类,用于构建线段树。在构建线段树的过程中,我们需要递归地构建左右子树,并根据左右子树的状态值来更新当前节点的状态值。
在主函数中,我们首先根据给定的数组 构建线段树,并对每个查询进行处理。对于每个查询,我们首先进行单点修改,然后查询整个区间的状态值,并将结果累加到答案中。
时间复杂度 ,空间复杂度 。其中 表示数组 的长度,而 表示查询的次数。
def max(a: int, b: int) -> int:
return a if a > b else b
class Node:
__slots__ = "l", "r", "s00", "s01", "s10", "s11"
def __init__(self, l: int, r: int):
self.l = l
self.r = r
self.s00 = self.s01 = self.s10 = self.s11 = 0
class SegmentTree:
__slots__ = "tr"
def __init__(self, n: int):
self.tr: List[Node | None] = [None] * (n << 2)
self.build(1, 1, n)
def build(self, u: int, l: int, r: int):
self.tr[u] = Node(l, r)
if l == r:
return
mid = (l + r) >> 1
self.build(u << 1, l, mid)
self.build(u << 1 | 1, mid + 1, r)
def query(self, u: int, l: int, r: int) -> int:
if self.tr[u].l >= l and self.tr[u].r <= r:
return self.tr[u].s11
mid = (self.tr[u].l + self.tr[u].r) >> 1
ans = 0
if r <= mid:
ans = self.query(u << 1, l, r)
if l > mid:
ans = max(ans, self.query(u << 1 | 1, l, r))
return ans
def pushup(self, u: int):
left, right = self.tr[u << 1], self.tr[u << 1 | 1]
self.tr[u].s00 = max(left.s00 + right.s10, left.s01 + right.s00)
self.tr[u].s01 = max(left.s00 + right.s11, left.s01 + right.s01)
self.tr[u].s10 = max(left.s10 + right.s10, left.s11 + right.s00)
self.tr[u].s11 = max(left.s10 + right.s11, left.s11 + right.s01)
def modify(self, u: int, x: int, v: int):
if self.tr[u].l == self.tr[u].r:
self.tr[u].s11 = max(0, v)
return
mid = (self.tr[u].l + self.tr[u].r) >> 1
if x <= mid:
self.modify(u << 1, x, v)
else:
self.modify(u << 1 | 1, x, v)
self.pushup(u)
class Solution:
def maximumSumSubsequence(self, nums: List[int], queries: List[List[int]]) -> int:
n = len(nums)
tree = SegmentTree(n)
for i, x in enumerate(nums, 1):
tree.modify(1, i, x)
ans = 0
mod = 10**9 + 7
for i, x in queries:
tree.modify(1, i + 1, x)
ans = (ans + tree.query(1, 1, n)) % mod
return ans
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
The problem is testing your ability to maintain state dynamically after array updates.
- question_mark
Expect hints towards using DP with careful state transitions or a segment tree to avoid recomputation.
- question_mark
Watch for edge cases with negative numbers or empty subsequences.
常见陷阱
外企场景- error
Recomputing the entire array from scratch after each query causing TLE.
- error
Ignoring the empty subsequence option when all elements are negative.
- error
Incorrectly updating adjacent states leading to invalid subsequences.
进阶变体
外企场景- arrow_right_alt
Compute maximum sum of non-adjacent elements with a fixed number of selections per query.
- arrow_right_alt
Allow selecting elements with at least k spacing between them instead of just one.
- arrow_right_alt
Queries that incrementally add to elements instead of replacing them, requiring cumulative DP updates.