返回介绍

solution / 2900-2999 / 2926.Maximum Balanced Subsequence Sum / README_EN

发布于 2024-06-17 01:02:58 字数 10277 浏览 0 评论 0 收藏 0

2926. Maximum Balanced Subsequence Sum

中文文档

Description

You are given a 0-indexed integer array nums.

A subsequence of nums having length k and consisting of indices i0 < i1 < ... < ik-1 is balanced if the following holds:

  • nums[ij] - nums[ij-1] >= ij - ij-1, for every j in the range [1, k - 1].

A subsequence of nums having length 1 is considered balanced.

Return _an integer denoting the maximum possible sum of elements in a balanced subsequence of _nums.

A subsequence of an array is a new non-empty array that is formed from the original array by deleting some (possibly none) of the elements without disturbing the relative positions of the remaining elements.

 

Example 1:

Input: nums = [3,3,5,6]
Output: 14
Explanation: In this example, the subsequence [3,5,6] consisting of indices 0, 2, and 3 can be selected.
nums[2] - nums[0] >= 2 - 0.
nums[3] - nums[2] >= 3 - 2.
Hence, it is a balanced subsequence, and its sum is the maximum among the balanced subsequences of nums.
The subsequence consisting of indices 1, 2, and 3 is also valid.
It can be shown that it is not possible to get a balanced subsequence with a sum greater than 14.

Example 2:

Input: nums = [5,-1,-3,8]
Output: 13
Explanation: In this example, the subsequence [5,8] consisting of indices 0 and 3 can be selected.
nums[3] - nums[0] >= 3 - 0.
Hence, it is a balanced subsequence, and its sum is the maximum among the balanced subsequences of nums.
It can be shown that it is not possible to get a balanced subsequence with a sum greater than 13.

Example 3:

Input: nums = [-2,-1]
Output: -1
Explanation: In this example, the subsequence [-1] can be selected.
It is a balanced subsequence, and its sum is the maximum among the balanced subsequences of nums.

 

Constraints:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

Solutions

Solution 1: Dynamic Programming + Binary Indexed Tree

According to the problem description, we can transform the inequality $nums[i] - nums[j] \ge i - j$ into $nums[i] - i \ge nums[j] - j$. Therefore, we consider defining a new array $arr$, where $arr[i] = nums[i] - i$. A balanced subsequence satisfies that for any $j < i$, $arr[j] \le arr[i]$. The problem is transformed into selecting an increasing subsequence in $arr$ such that the corresponding sum in $nums$ is maximized.

Suppose $i$ is the index of the last element in the subsequence, then we consider the index $j$ of the second to last element in the subsequence. If $arr[j] \le arr[i]$, we can consider whether to add $j$ to the subsequence.

Therefore, we define $f[i]$ as the maximum sum of $nums$ when the index of the last element in the subsequence is $i$. The answer is $\max_{i=0}^{n-1} f[i]$.

The state transition equation is:

$$ f[i] = \max(\max_{j=0}^{i-1} f[j], 0) + nums[i] $$

where $j$ satisfies $arr[j] \le arr[i]$.

We can use a Binary Indexed Tree to maintain the maximum value of the prefix, i.e., for each $arr[i]$, we maintain the maximum value of $f[i]$ in the prefix $arr[0..i]$.

The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $nums$.

class BinaryIndexedTree:
  def __init__(self, n: int):
    self.n = n
    self.c = [-inf] * (n + 1)

  def update(self, x: int, v: int):
    while x <= self.n:
      self.c[x] = max(self.c[x], v)
      x += x & -x

  def query(self, x: int) -> int:
    mx = -inf
    while x:
      mx = max(mx, self.c[x])
      x -= x & -x
    return mx


class Solution:
  def maxBalancedSubsequenceSum(self, nums: List[int]) -> int:
    arr = [x - i for i, x in enumerate(nums)]
    s = sorted(set(arr))
    tree = BinaryIndexedTree(len(s))
    for i, x in enumerate(nums):
      j = bisect_left(s, x - i) + 1
      v = max(tree.query(j), 0) + x
      tree.update(j, v)
    return tree.query(len(s))
class BinaryIndexedTree {
  private int n;
  private long[] c;
  private final long inf = 1L << 60;

  public BinaryIndexedTree(int n) {
    this.n = n;
    c = new long[n + 1];
    Arrays.fill(c, -inf);
  }

  public void update(int x, long v) {
    while (x <= n) {
      c[x] = Math.max(c[x], v);
      x += x & -x;
    }
  }

  public long query(int x) {
    long mx = -inf;
    while (x > 0) {
      mx = Math.max(mx, c[x]);
      x -= x & -x;
    }
    return mx;
  }
}

class Solution {
  public long maxBalancedSubsequenceSum(int[] nums) {
    int n = nums.length;
    int[] arr = new int[n];
    for (int i = 0; i < n; ++i) {
      arr[i] = nums[i] - i;
    }
    Arrays.sort(arr);
    int m = 0;
    for (int i = 0; i < n; ++i) {
      if (i == 0 || arr[i] != arr[i - 1]) {
        arr[m++] = arr[i];
      }
    }
    BinaryIndexedTree tree = new BinaryIndexedTree(m);
    for (int i = 0; i < n; ++i) {
      int j = search(arr, nums[i] - i, m) + 1;
      long v = Math.max(tree.query(j), 0) + nums[i];
      tree.update(j, v);
    }
    return tree.query(m);
  }

  private int search(int[] nums, int x, int r) {
    int l = 0;
    while (l < r) {
      int mid = (l + r) >> 1;
      if (nums[mid] >= x) {
        r = mid;
      } else {
        l = mid + 1;
      }
    }
    return l;
  }
}
class BinaryIndexedTree {
private:
  int n;
  vector<long long> c;
  const long long inf = 1e18;

public:
  BinaryIndexedTree(int n) {
    this->n = n;
    c.resize(n + 1, -inf);
  }

  void update(int x, long long v) {
    while (x <= n) {
      c[x] = max(c[x], v);
      x += x & -x;
    }
  }

  long long query(int x) {
    long long mx = -inf;
    while (x > 0) {
      mx = max(mx, c[x]);
      x -= x & -x;
    }
    return mx;
  }
};

class Solution {
public:
  long long maxBalancedSubsequenceSum(vector<int>& nums) {
    int n = nums.size();
    vector<int> arr(n);
    for (int i = 0; i < n; ++i) {
      arr[i] = nums[i] - i;
    }
    sort(arr.begin(), arr.end());
    arr.erase(unique(arr.begin(), arr.end()), arr.end());
    int m = arr.size();
    BinaryIndexedTree tree(m);
    for (int i = 0; i < n; ++i) {
      int j = lower_bound(arr.begin(), arr.end(), nums[i] - i) - arr.begin() + 1;
      long long v = max(tree.query(j), 0LL) + nums[i];
      tree.update(j, v);
    }
    return tree.query(m);
  }
};
const inf int = 1e18

type BinaryIndexedTree struct {
  n int
  c []int
}

func NewBinaryIndexedTree(n int) BinaryIndexedTree {
  c := make([]int, n+1)
  for i := range c {
    c[i] = -inf
  }
  return BinaryIndexedTree{n: n, c: c}
}

func (bit *BinaryIndexedTree) update(x, v int) {
  for x <= bit.n {
    bit.c[x] = max(bit.c[x], v)
    x += x & -x
  }
}

func (bit *BinaryIndexedTree) query(x int) int {
  mx := -inf
  for x > 0 {
    mx = max(mx, bit.c[x])
    x -= x & -x
  }
  return mx
}

func maxBalancedSubsequenceSum(nums []int) int64 {
  n := len(nums)
  arr := make([]int, n)
  for i, x := range nums {
    arr[i] = x - i
  }
  sort.Ints(arr)
  m := 0
  for i, x := range arr {
    if i == 0 || x != arr[i-1] {
      arr[m] = x
      m++
    }
  }
  arr = arr[:m]
  tree := NewBinaryIndexedTree(m)
  for i, x := range nums {
    j := sort.SearchInts(arr, x-i) + 1
    v := max(tree.query(j), 0) + x
    tree.update(j, v)
  }
  return int64(tree.query(m))
}
class BinaryIndexedTree {
  private n: number;
  private c: number[];

  constructor(n: number) {
    this.n = n;
    this.c = Array(n + 1).fill(-Infinity);
  }

  update(x: number, v: number): void {
    while (x <= this.n) {
      this.c[x] = Math.max(this.c[x], v);
      x += x & -x;
    }
  }

  query(x: number): number {
    let mx = -Infinity;
    while (x > 0) {
      mx = Math.max(mx, this.c[x]);
      x -= x & -x;
    }
    return mx;
  }
}

function maxBalancedSubsequenceSum(nums: number[]): number {
  const n = nums.length;
  const arr = Array(n).fill(0);
  for (let i = 0; i < n; ++i) {
    arr[i] = nums[i] - i;
  }
  arr.sort((a, b) => a - b);
  let m = 0;
  for (let i = 0; i < n; ++i) {
    if (i === 0 || arr[i] !== arr[i - 1]) {
      arr[m++] = arr[i];
    }
  }
  arr.length = m;
  const tree = new BinaryIndexedTree(m);
  const search = (nums: number[], x: number): number => {
    let [l, r] = [0, nums.length];
    while (l < r) {
      const mid = (l + r) >> 1;
      if (nums[mid] >= x) {
        r = mid;
      } else {
        l = mid + 1;
      }
    }
    return l;
  };
  for (let i = 0; i < n; ++i) {
    const j = search(arr, nums[i] - i) + 1;
    const v = Math.max(tree.query(j), 0) + nums[i];
    tree.update(j, v);
  }
  return tree.query(m);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文