Leetcode每日打卡第9天

题目

不包含相邻元素的子序列的最大和

给你一个整数数组 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

思路

python3代码

class SegNode:
    def __init__(self) -> None:
        self.v00 = self.v01 = self.v10 = self.v11 = 0
    
    def set_value(self, v: int) -> None:
        self.v00 = self.v01 = self.v10 = 0
        self.v11 = max(v, 0)
    
    def best(self) -> int:
        return self.v11

class SegTree:
    def __init__(self, n: int) -> None:
        self.n = n
        self.tree = [SegNode() for _ in range(n * 4 + 1)]
    
    def init(self, nums: List[int]) -> None:
        def internal_init(x: int, l: int, r: int) -> None:
            if l == r:
                self.tree[x].set_value(nums[l - 1])
                return
            mid = (l + r) // 2
            internal_init(x * 2, l, mid)
            internal_init(x * 2 + 1, mid + 1, r)
            self.pushup(x)
        internal_init(1, 1, self.n)
    
    def update(self, x: int, v: int) -> None:
        def internal_update(x: int, l: int, r: int, pos: int, v: int) -> None:
            if l > pos or r < pos:
                return
            if l == r:
                self.tree[x].set_value(v)
                return
            mid = (l + r) // 2
            internal_update(x * 2, l, mid, pos, v)
            internal_update(x * 2 + 1, mid + 1, r, pos, v)
            self.pushup(x)
        internal_update(1, 1, self.n, x + 1, v)
    
    def query(self) -> int:
        return self.tree[1].best()

    def pushup(self, x: int) -> None:
        tree_ = self.tree

        l, r = x * 2, x * 2 + 1
        tree_[x].v00 = max(tree_[l].v00 + tree_[r].v10, tree_[l].v01 + tree_[r].v00)
        tree_[x].v01 = max(tree_[l].v00 + tree_[r].v11, tree_[l].v01 + tree_[r].v01)
        tree_[x].v10 = max(tree_[l].v10 + tree_[r].v10, tree_[l].v11 + tree_[r].v00)
        tree_[x].v11 = max(tree_[l].v10 + tree_[r].v11, tree_[l].v11 + tree_[r].v01)

class Solution:
    def maximumSumSubsequence(self, nums: List[int], queries: List[List[int]]) -> int:
        tree = SegTree(len(nums))
        tree.init(nums)
        
        ans = 0
        for x, v in queries:
            tree.update(x, v)
            ans += tree.query()
        return ans % (10**9 + 7)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值