diff --git a/solution/2600-2699/2609.Find the Longest Balanced Substring of a Binary String/README.md b/solution/2600-2699/2609.Find the Longest Balanced Substring of a Binary String/README.md index 8489e6a31217f..8396e74bfc5d5 100644 --- a/solution/2600-2699/2609.Find the Longest Balanced Substring of a Binary String/README.md +++ b/solution/2600-2699/2609.Find the Longest Balanced Substring of a Binary String/README.md @@ -66,7 +66,7 @@ 遍历字符串 $s$,对于当前字符 $c$: - 如果当前字符为 `'0'`,我们判断此时 $one$ 是否大于 $0$,是则将 $zero$ 和 $one$ 重置为 $0$,接下来将 $zero$ 加 $1$。 -- 如果当前字符为 `'1'`,则将 $one$ 加 $1$,并更新答案为 $ans = max(ans, 2 \times min(one, zero))$。 +- 如果当前字符为 `'1'`,则将 $one$ 加 $1$,并更新答案为 $ans = \max(ans, 2 \times \min(one, zero))$。 遍历结束后,即可得到最长的平衡子串的长度。 @@ -326,7 +326,7 @@ impl Solution { if s.as_bytes()[k] == b'1' { cnt += 1; } else if cnt > 0 { - return false + return false; } } @@ -369,7 +369,7 @@ impl Solution { zero += 1; } else { one += 1; - ans = std::cmp::max(ans, std::cmp::min(zero, one) * 2) + ans = std::cmp::max(ans, std::cmp::min(zero, one) * 2); } } diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README.md b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README.md index ab913a50db6f6..510da5c7b509b 100644 --- a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README.md +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README.md @@ -67,6 +67,26 @@ nums[3] - nums[0] >= 3 - 0 。 +**方法一:动态规划 + 树状数组** + +根据题目描述,我们可以将不等式 $nums[i] - nums[j] \ge i - j$ 转化为 $nums[i] - i \ge nums[j] - j$,因此,我们考虑定义一个新数组 $arr$,其中 $arr[i] = nums[i] - i$,那么平衡子序列满足对于任意 $j \lt i$,都有 $arr[j] \le arr[i]$。即题目转换为求在 $arr$ 中选出一个递增子序列,使得对应的 $nums$ 的和最大。 + +假设 $i$ 是子序列中最后一个元素的下标,那么我们考虑子序列倒数第二个元素的下标 $j$,如果 $arr[j] \le arr[i]$,我们可以考虑是否要将 $j$ 加入到子序列中。 + +因此,我们定义 $f[i]$ 表示子序列最后一个元素的下标为 $i$ 时,对应的 $nums$ 的最大和,那么答案为 $\max_{i=0}^{n-1} f[i]$。 + +状态转移方程为: + +$$ +f[i] = \max(\max_{j=0}^{i-1} f[j], 0) + nums[i] +$$ + +其中 $j$ 满足 $arr[j] \le arr[i]$。 + +我们可以使用树状数组来维护前缀的最大值,即对于每个 $arr[i]$,我们维护前缀 $arr[0..i]$ 中 $f[i]$ 的最大值。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。 + ### **Python3** @@ -74,7 +94,34 @@ nums[3] - nums[0] >= 3 - 0 。 ```python - +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)) ``` ### **Java** @@ -82,19 +129,248 @@ nums[3] - nums[0] >= 3 - 0 。 ```java - +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; + } +} ``` ### **C++** ```cpp - +class BinaryIndexedTree { +private: + int n; + vector 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& nums) { + int n = nums.size(); + vector 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); + } +}; ``` ### **Go** ```go +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)) +} +``` +### **TypeScript** + +```ts +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); +} ``` ### **...** diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README_EN.md b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README_EN.md index ebf76696c055c..7aef6a37e364c 100644 --- a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README_EN.md +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/README_EN.md @@ -61,30 +61,306 @@ It is a balanced subsequence, and its sum is the maximum among the balanced subs ## 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$. + ### **Python3** ```python - +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)) ``` ### **Java** ```java - +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; + } +} ``` ### **C++** ```cpp - +class BinaryIndexedTree { +private: + int n; + vector 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& nums) { + int n = nums.size(); + vector 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); + } +}; ``` ### **Go** ```go +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)) +} +``` +### **TypeScript** + +```ts +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); +} ``` ### **...** diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.cpp b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.cpp new file mode 100644 index 0000000000000..1cf74a14a4dbe --- /dev/null +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.cpp @@ -0,0 +1,49 @@ +class BinaryIndexedTree { +private: + int n; + vector 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& nums) { + int n = nums.size(); + vector 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); + } +}; \ No newline at end of file diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.go b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.go new file mode 100644 index 0000000000000..845cdd7871731 --- /dev/null +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.go @@ -0,0 +1,54 @@ +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)) +} \ No newline at end of file diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.java b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.java new file mode 100644 index 0000000000000..f9db775c2a597 --- /dev/null +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.java @@ -0,0 +1,64 @@ +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; + } +} \ No newline at end of file diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.py b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.py new file mode 100644 index 0000000000000..d069bb1810434 --- /dev/null +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.py @@ -0,0 +1,28 @@ +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)) diff --git a/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.ts b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.ts new file mode 100644 index 0000000000000..6782ed0d094f4 --- /dev/null +++ b/solution/2900-2999/2926.Maximum Balanced Subsequence Sum/Solution.ts @@ -0,0 +1,60 @@ +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); +}