You're given a 0-indexed integer arraynums and need to find the maximum sum of a special type of subsequence called a balanced subsequence.
A subsequence with indices i₀ < i₁ < ... < iₖ₋₁ is balanced if for every consecutive pair of elements:
nums[iⱼ] - nums[iⱼ₋₁] ≥ iⱼ - iⱼ₋₁ for all j ∈ [1, k-1]
In simpler terms, the value difference between consecutive elements must be at least as large as their index difference. This ensures the subsequence grows "fast enough" relative to how spread out the indices are.
Goal: Return the maximum possible sum of elements in any balanced subsequence. Note that a single element is always considered balanced.
Example: For nums = [3, -1, 1, 2], the subsequence at indices [0, 3] gives us [3, 2]. Check: 2 - 3 = -1 and 3 - 0 = 3, so -1 ≥ 3 is false, making this not balanced.
Input & Output
example_1.py — Basic case with mixed values
$Input:nums = [3, -1, 1, 2]
›Output:3
💡 Note:The best balanced subsequence is just the single element [3] at index 0. Other subsequences like [3, 2] fail the balance check: (2-3) = -1 < (3-0) = 3.
example_2.py — All negative values
$Input:nums = [-1, -2, -3]
›Output:-1
💡 Note:Since all values are negative, the best strategy is to pick the single largest element, which is -1 at index 0.
example_3.py — Increasing subsequence
$Input:nums = [5, 6, 7, 8]
›Output:26
💡 Note:The entire array forms a balanced subsequence: differences are [1,1,1] and index gaps are [1,1,1], so 1 ≥ 1 for all pairs. Sum = 5+6+7+8 = 26.
Constraints
1 ≤ nums.length ≤ 105
-109 ≤ nums[i] ≤ 109
The subsequence must maintain original relative order of elements
Visualization
Tap to expand
Understanding the Visualization
1
Transform Problem
Convert balance condition to: transformed[j] ≥ transformed[i] where transformed[k] = nums[k] - k
2
Coordinate Compression
Map potentially large value ranges to compact array indices for efficient processing
3
Dynamic Programming
Use segment tree to quickly find the best previous position that satisfies the constraint
4
Optimal Selection
Build up the maximum sum by considering each position and its optimal predecessors
Key Takeaway
🎯 Key Insight: Transform the balance condition algebraically and use advanced data structures to handle the complex constraint efficiently in O(n log n) time.
The optimal approach uses dynamic programming with coordinate compression and segment trees. Transform the balance condition to nums[j] - j ≥ nums[i] - i, compress coordinates, and use segment trees for efficient range maximum queries. This achieves O(n log n) time complexity while handling the complex subsequence constraints elegantly.
Common Approaches
Approach
Time
Space
Notes
✓
Dynamic Programming with Coordinate Compression
O(n log n)
O(n)
Use DP with coordinate compression and segment tree for efficient range maximum queries
Brute Force (Try All Subsequences)
O(n × 2ⁿ)
O(n)
Generate all possible subsequences and check balance condition
Dynamic Programming with Coordinate Compression — Algorithm Steps
Transform each element: create pairs (nums[i] - i, nums[i]) for coordinate compression
Sort and compress coordinates to map large ranges to smaller indices
Use segment tree to maintain maximum DP values for each compressed coordinate
For each element, query maximum from valid previous positions and update current position
Return the overall maximum found
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Transform Values
Convert nums[i] to nums[i] - i for easier comparison
2
Compress Coordinates
Map large value ranges to smaller indices
3
DP with Segment Tree
Query max from valid positions and update current
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define MAXN 100005
typedef struct {
int valMinusIdx, val, idx;
} Item;
long long tree[4 * MAXN];
int coords[MAXN];
int coordMap[200005];
int coordCount;
void initSegTree(int size) {
for (int i = 0; i < 4 * size; i++) {
tree[i] = LLONG_MIN / 2;
}
}
void updateSegTree(int node, int start, int end, int idx, long long val) {
if (start == end) {
if (val > tree[node]) tree[node] = val;
} else {
int mid = (start + end) / 2;
if (idx <= mid) {
updateSegTree(2 * node, start, mid, idx, val);
} else {
updateSegTree(2 * node + 1, mid + 1, end, idx, val);
}
long long left = tree[2 * node], right = tree[2 * node + 1];
tree[node] = (left > right) ? left : right;
}
}
long long querySegTree(int node, int start, int end, int l, int r) {
if (r < start || end < l) return LLONG_MIN / 2;
if (l <= start && end <= r) return tree[node];
int mid = (start + end) / 2;
long long left = querySegTree(2 * node, start, mid, l, r);
long long right = querySegTree(2 * node + 1, mid + 1, end, l, r);
return (left > right) ? left : right;
}
int compareItems(const void* a, const void* b) {
return ((Item*)a)->idx - ((Item*)b)->idx;
}
int compareInts(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
long long maxBalancedSubsequenceSum(int* nums, int n) {
Item arr[MAXN];
int tempCoords[MAXN];
for (int i = 0; i < n; i++) {
arr[i].valMinusIdx = nums[i] - i;
arr[i].val = nums[i];
arr[i].idx = i;
tempCoords[i] = nums[i] - i;
}
// Coordinate compression
qsort(tempCoords, n, sizeof(int), compareInts);
coordCount = 0;
coords[coordCount++] = tempCoords[0];
for (int i = 1; i < n; i++) {
if (tempCoords[i] != tempCoords[i-1]) {
coords[coordCount++] = tempCoords[i];
}
}
// Create coordinate mapping (simplified for this range)
memset(coordMap, -1, sizeof(coordMap));
for (int i = 0; i < coordCount; i++) {
coordMap[coords[i] + 100000] = i; // Offset for negative values
}
initSegTree(coordCount);
long long maxSum = nums[0];
for (int i = 1; i < n; i++) {
if (nums[i] > maxSum) maxSum = nums[i];
}
qsort(arr, n, sizeof(Item), compareItems);
for (int i = 0; i < n; i++) {
int compressedIdx = coordMap[arr[i].valMinusIdx + 100000];
long long prevMax = querySegTree(1, 0, coordCount - 1, 0, compressedIdx);
long long currentDp = arr[i].val;
if (prevMax > LLONG_MIN / 2) {
long long candidate = prevMax + arr[i].val;
if (candidate > currentDp) currentDp = candidate;
}
if (currentDp > maxSum) maxSum = currentDp;
updateSegTree(1, 0, coordCount - 1, compressedIdx, currentDp);
}
return maxSum;
}
int main() {
int nums[MAXN];
int n = 0;
char c;
// Simple input parsing
scanf("%c", &c); // skip '['
while (scanf("%d%c", &nums[n], &c)) {
n++;
if (c == ']') break;
}
printf("%lld\n", maxBalancedSubsequenceSum(nums, n));
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n log n)
O(n log n) for sorting and coordinate compression, O(n log n) for segment tree operations
n
2n
⚡ Linearithmic
Space Complexity
O(n)
Space for coordinate compression arrays and segment tree structure
n
2n
⚡ Linearithmic Space
26.3K Views
MediumFrequency
~35 minAvg. Time
856 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.