100306. 不包含相邻元素的子序列的最大和
给你一个整数数组 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] <= 105
1 <= queries.length <= 5 * 104
queries[i] == [posi, xi]
0 <= posi <= nums.length - 1
-105 <= xi <= 105
原站题解
javascript 解法, 执行用时: 389 ms, 内存消耗: 86.7 MB, 提交时间: 2024-10-31 00:13:26
/** * @param {number[]} nums * @param {number[][]} queries * @return {number} */ var maximumSumSubsequence = function(nums, queries) { const n = nums.length; // 4 个数分别保存 f00, f01, f10, f11 const t = Array.from({length: 2 << (32 - Math.clz32(n))}, () => [0, 0, 0, 0]); function maintain(o) { const a = t[o * 2], b = t[o * 2 + 1]; t[o][0] = Math.max(a[0] + b[2], a[1] + b[0]); t[o][1] = Math.max(a[0] + b[3], a[1] + b[1]); t[o][2] = Math.max(a[2] + b[2], a[3] + b[0]); t[o][3] = Math.max(a[2] + b[3], a[3] + b[1]); } // 用 nums 初始化线段树 function build(o, l, r) { if (l === r) { t[o][3] = Math.max(nums[l], 0); return; } const m = Math.floor((l + r) / 2); build(o * 2, l, m); build(o * 2 + 1, m + 1, r); maintain(o); } // 把 nums[i] 改成 val function update(o, l, r, i, val) { if (l === r) { t[o][3] = Math.max(val, 0); return; } const m = Math.floor((l + r) / 2); if (i <= m) { update(o * 2, l, m, i, val); } else { update(o * 2 + 1, m + 1, r, i, val); } maintain(o); } build(1, 0, n - 1); let ans = 0; for (const [i, x] of queries) { update(1, 0, n - 1, i, x); ans += t[1][3]; // 注意 f11 没有任何限制,也就是整个数组的打家劫舍 } return ans % 1_000_000_007; };
cpp 解法, 执行用时: 204 ms, 内存消耗: 89.4 MB, 提交时间: 2024-05-26 19:13:10
class Solution { // 4 个数分别保存 f00, f01, f10, f11 vector<array<unsigned int, 4>> t; void maintain(int o) { auto& a = t[o * 2], b = t[o * 2 + 1]; t[o] = { max(a[0] + b[2], a[1] + b[0]), max(a[0] + b[3], a[1] + b[1]), max(a[2] + b[2], a[3] + b[0]), max(a[2] + b[3], a[3] + b[1]), }; } // 用 nums 初始化线段树 void build(vector<int>& nums, int o, int l, int r) { if (l == r) { t[o][3] = max(nums[l], 0); return; } int m = (l + r) / 2; build(nums, o * 2, l, m); build(nums, o * 2 + 1, m + 1, r); maintain(o); }; // 把 nums[i] 改成 val void update(int o, int l, int r, int i, int val) { if (l == r) { t[o][3] = max(val, 0); return; } int m = (l + r) / 2; if (i <= m) { update(o * 2, l, m, i, val); } else { update(o * 2 + 1, m + 1, r, i, val); } maintain(o); }; public: int maximumSumSubsequence(vector<int>& nums, vector<vector<int>>& queries) { int n = nums.size(); t.resize(2 << (32 - __builtin_clz(n))); build(nums, 1, 0, n - 1); long long ans = 0; for (auto& q : queries) { update(1, 0, n - 1, q[0], q[1]); ans += t[1][3]; // 注意 f11 没有任何限制,也就是整个数组的打家劫舍 } return ans % 1'000'000'007; } };
java 解法, 执行用时: 63 ms, 内存消耗: 59.8 MB, 提交时间: 2024-05-26 19:12:58
class Solution { public int maximumSumSubsequence(int[] nums, int[][] queries) { int n = nums.length; // 4 个数分别保存 f00, f01, f10, f11 long[][] t = new long[2 << (32 - Integer.numberOfLeadingZeros(n))][4]; build(t, nums, 1, 0, n - 1); long ans = 0; for (int[] q : queries) { update(t, 1, 0, n - 1, q[0], q[1]); ans += t[1][3]; // 注意 f11 没有任何限制,也就是整个数组的打家劫舍 } return (int) (ans % 1_000_000_007); } private void maintain(long[][] t, int o) { long[] a = t[o * 2], b = t[o * 2 + 1]; t[o][0] = Math.max(a[0] + b[2], a[1] + b[0]); t[o][1] = Math.max(a[0] + b[3], a[1] + b[1]); t[o][2] = Math.max(a[2] + b[2], a[3] + b[0]); t[o][3] = Math.max(a[2] + b[3], a[3] + b[1]); } // 用 nums 初始化线段树 private void build(long[][] t, int[] nums, int o, int l, int r) { if (l == r) { t[o][3] = Math.max(nums[l], 0); return; } int m = (l + r) / 2; build(t, nums, o * 2, l, m); build(t, nums, o * 2 + 1, m + 1, r); maintain(t, o); } // 把 nums[i] 改成 val private void update(long[][] t, int o, int l, int r, int i, int val) { if (l == r) { t[o][3] = Math.max(val, 0); return; } int m = (l + r) / 2; if (i <= m) { update(t, o * 2, l, m, i, val); } else { update(t, o * 2 + 1, m + 1, r, i, val); } maintain(t, o); } }
python3 解法, 执行用时: 2322 ms, 内存消耗: 58.1 MB, 提交时间: 2024-05-26 19:12:25
class Solution: def maximumSumSubsequence(self, nums: List[int], queries: List[List[int]]) -> int: n = len(nums) # 4 个数分别保存 f00, f01, f10, f11 t = [[0] * 4 for _ in range(2 << n.bit_length())] def maintain(o: int): a, b = t[o * 2], t[o * 2 + 1] t[o][0] = max(a[0] + b[2], a[1] + b[0]) t[o][1] = max(a[0] + b[3], a[1] + b[1]) t[o][2] = max(a[2] + b[2], a[3] + b[0]) t[o][3] = max(a[2] + b[3], a[3] + b[1]) # 用 nums 初始化线段树 def build(o: int, l: int, r: int) -> None: if l == r: t[o][3] = max(nums[l], 0) return m = (l + r) // 2 build(o * 2, l, m) build(o * 2 + 1, m + 1, r) maintain(o) # 把 nums[i] 改成 val def update(o: int, l: int, r: int, i: int, val: int) -> None: if l == r: t[o][3] = max(val, 0) return m = (l + r) // 2 if i <= m: update(o * 2, l, m, i, val) else: update(o * 2 + 1, m + 1, r, i, val) maintain(o) build(1, 0, n - 1) ans = 0 for i, x in queries: update(1, 0, n - 1, i, x) ans += t[1][3] # 注意 f11 没有任何限制,也就是整个数组的打家劫舍 return ans % 1_000_000_007
golang 解法, 执行用时: 103 ms, 内存消耗: 14.1 MB, 提交时间: 2024-05-26 19:12:11
// f00 表示第一个数一定不选,最后一个数一定不选 // f01 表示第一个数一定不选,最后一个数可选可不选 // f10 表示第一个数可选可不选,最后一个数一定不选 // f11 表示第一个数可选可不选,最后一个数可选可不选,也就是没有任何限制 type data struct{ f00, f01, f10, f11 int } type seg []data func (t seg) maintain(o int) { a, b := t[o<<1], t[o<<1|1] t[o] = data{ max(a.f00+b.f10, a.f01+b.f00), max(a.f00+b.f11, a.f01+b.f01), max(a.f10+b.f10, a.f11+b.f00), max(a.f10+b.f11, a.f11+b.f01), } } func (t seg) build(a []int, o, l, r int) { if l == r { t[o].f11 = max(a[l], 0) return } m := (l + r) >> 1 t.build(a, o<<1, l, m) t.build(a, o<<1|1, m+1, r) t.maintain(o) } func (t seg) update(o, l, r, i, val int) { if l == r { t[o].f11 = max(val, 0) return } m := (l + r) >> 1 if i <= m { t.update(o<<1, l, m, i, val) } else { t.update(o<<1|1, m+1, r, i, val) } t.maintain(o) } func maximumSumSubsequence(nums []int, queries [][]int) (ans int) { n := len(nums) t := make(seg, 2<<bits.Len(uint(n-1))) t.build(nums, 1, 0, n-1) for _, q := range queries { t.update(1, 0, n-1, q[0], q[1]) ans += t[1].f11 // 注意 f11 没有任何限制,也就是整个数组的打家劫舍 } return ans % 1_000_000_007 }