leetcode:2926. 平衡子序列的最大和 【树状数组维护最大前缀和】

题目链接

lc2926

题目描述

在这里插入图片描述

题目思路

定义b[i] = nums[i] - i
目标是从b中找到一个非降子序列使得元素和最大
# b[i] = nums[i] - i
# 找到b的一个非降子序列使得元素和最大
# f[i]: 子序列最后一个数下标是i,对应的最大子序列
# f[i] = max (max f[j], 0) + nums[i] (j < i and b[j] <= b[i])
# 也就是维护f[j]的前缀最大值
# 10 ** 9: 离散化处理 + 重新标序号

ac code

# 树状数组模板(维护前缀最大值)
class BIT:
    def __init__(self, n: int):
        self.tree = [-inf] * n

    def update(self, i: int, val: int) -> None:
        while i < len(self.tree):
            self.tree[i] = max(self.tree[i], val)
            i += i & -i

    def pre_max(self, i: int) -> int:
        mx = -inf
        while i > 0:
            mx = max(mx, self.tree[i])
            i -= i & -i
        return mx


class Solution:
    def maxBalancedSubsequenceSum(self, nums: List[int]) -> int:
        n = len(nums)
        # b[i] = nums[i] - i
        # 找到b的一个非降子序列使得元素和最大
        # f[i]: 子序列最后一个数下标是i,对应的最大子序列
        # f[i] = max (max f[j], 0) + nums[i] (j < i and b[j] <= b[i])
        # 也就是维护f[j]的前缀最大值
        # 10 ** 9: 离散化处理 + 重新标序号
        b = sorted(set(x - i for i, x in enumerate(nums)))
        t = BIT(len(b) + 1) # 经典初始化
        for i, x in enumerate(nums):
            j = bisect_left(b, x - i) + 1 # 找到b[i]离散化后的位置
            f = max(t.pre_max(j), 0) + x # 计算f[i]
            t.update(j, f)
        return t.pre_max(len(b)) # 所有f的最大值
            



树状数组维护前缀最大值模版

# 树状数组模板(维护前缀最大值)
class BIT:
    def __init__(self, n: int):
        self.tree = [-inf] * n

    def update(self, i: int, val: int) -> None:
        while i < len(self.tree):
            self.tree[i] = max(self.tree[i], val)
            i += i & -i

    def pre_max(self, i: int) -> int:
        mx = -inf
        while i > 0:
            mx = max(mx, self.tree[i])
            i -= i & -i
        return mx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白速龙王的回眸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值