Monotonic Threshold Span Synthesizer — Problem Statement & Solution Guide

Dynamic ProgrammingHardDivide and Conquer DP
TimeO(N log N)
|
SpaceO(N)

Quick Answer & Algorithm Key Takeaway

Master coding challenges related to Dynamic Programming and solve the Monotonic Threshold Span Synthesizer 2 problem optimally.

TopicDynamic Programming
PatternDivide and Conquer DP
TimeO(N log N)
SpaceO(N)

Problem Description

Monotonic Threshold Span Synthesizer 2

You are given an array A of N integers. The array must be split into one or more contiguous segments. For a segment that covers indices l through r (1‑based), its range is defined as max(A[l..r]) – min(A[l..r]). The cost of a partition is the sum of the ranges of all its segments. Your task is to determine the minimum possible cost over all valid partitions of the array.

Input format: The first line contains a single integer N (1 ≤ N ≤ 10^5). The second line contains N space‑separated integers A[1], A[2], …, A[N] where |A[i]| ≤ 10^9.

Output format: Output a single integer – the minimum total cost achievable.

The problem can be solved with dynamic programming: let dp[i] be the minimum cost to partition the prefix A[1..i]. Then dp[i] = min_{0≤j<i} (dp[j] + cost(j+1,i)). The cost function satisfies the quadrangle inequality, which guarantees that the optimal j for dp[i] is non‑decreasing as i increases. This monotonicity allows the use of divide‑and‑conquer optimization to compute all dp[i] in O(N log N) time.

Examples

The following examples illustrate the input, expected output, and a step‑by‑step reasoning for each case.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Monotonic Threshold Span Synthesizer"

hard

WHY DOES IT MATTER?

This pattern—DP combined with monotonic stacks and range‑update data structures—is a cornerstone for problems where a cost depends on dynamic extrema over subarrays. Mastery of this technique unlocks efficient solutions for a whole class of partitioning and sliding‑window optimization problems that appear frequently in high‑frequency trading, log analytics, and large‑scale data pipelines.

OPTIMIZATION CHALLENGE

The key insight is that the contribution of the new element to the range of any candidate segment is either +Δmax or -Δmin, and these deltas are constant over contiguous intervals of start positions. By representing those intervals with range‑add operations on a segment tree, we avoid recomputing the range for each start position individually.

REAL-WORLD CONNECTION

Imagine a streaming sensor network where each sensor batch must be shipped together; the shipping cost equals the temperature spread within the batch. Using monotonic stacks is akin to keeping a live view of the hottest and coldest sensors, while the segment tree aggregates the cheapest shipping plan for all batches seen so far.

When coding this in an interview, first write the DP recurrence, then sketch the monotonic‑stack update rules before pulling out the segment tree. Keep the tree interface minimal (rangeAdd(l,r,val) and pointQuery(pos)) to stay focused and avoid bugs.

COMPLEXITY AT A GLANCE

⏱ Time:O(N log N)
💾 Space:O(N)

Core Theory — Why This Approach?

The problem can be modeled as a classic one‑dimensional DP: let dp[i] be the minimum cost to partition the prefix A[1..i]. For each possible last segment ending at i we would need dp[j‑1] + (max_{j..i} - min_{j..i}) for some j ≤ i, which leads to an O(N^2) recurrence. The naïve double loop fails for N up to 2·10^5 because the quadratic term blows up both time and memory. The optimal paradigm combines DP with a data structure that can maintain the effect of extending the current segment while keeping track of the changing maximum and minimum. By processing the array left‑to‑right and using two monotonic stacks (one decreasing for maxima, one increasing for minima) we can identify intervals where the current max or min changes. A segment tree (or Fenwick tree with range‑add / point‑query) stores dp values and supports range additions that reflect the contribution of the new element to all candidate segments. Each element triggers at most O(1) stack pops and O(log N) segment‑tree updates, yielding an overall O(N log N) solution.

Interview Questions on This Problem

Q1How would you compute the minimum total range cost for partitioning an array into contiguous segments in O(N log N) time?

Use DP where dp[i] is the optimal cost for the prefix ending at i. Maintain two monotonic stacks to track the positions where the current maximum and minimum change. With a segment tree that supports range add and point query, update dp values for the affected intervals whenever a stack pop occurs, and set dp[i] = query(i) after processing element i.

Q2Why can a simple greedy split (e.g., cut whenever the current range exceeds a threshold) not guarantee the optimal cost?

Greedy decisions are local and ignore how a larger range now might enable a much smaller range later, affecting the total sum. The optimal partition balances the trade‑off between extending a segment (which may increase its range) and starting a new segment (which adds a new range term). Only a DP that considers all possible cut positions can capture this global optimum.

Q3Explain how monotonic stacks help convert the O(N^2) DP transition into O(N log N).

When extending the segment to the right, the maximum can only increase when a larger element appears, and the minimum can only decrease when a smaller element appears. Monotonic stacks store indices where these changes happen, allowing us to batch‑apply the same delta to a contiguous range of dp states via a segment tree. Each element causes at most one push and a few pops, turning the quadratic number of transitions into linear stack operations plus logarithmic tree updates.

Examples

Example 1

Input

5
1 3 2 5 4

Output

3

Explanation: We evaluate all possible partitions: - Whole array: range = 5 – 1 = 4. - Split after index 3: segments [1,3,2] (range 3–1=2) and [5,4] (range 5–4=1). Total = 3. - Other splits give larger totals. Thus the minimal cost is 3.

Example 2

Input

4
10 1 10 1

Output

9

Explanation: Possible partitions: - Whole array: range = 10 – 1 = 9. - Split into [10,1] and [10,1]: each range 9, total 18. - Split into [10] and [1,10,1]: ranges 0 and 9, total 9. - Split into [10,1,10] and [1]: ranges 9 and 0, total 9. The smallest achievable cost is 9.

Example 3

Input

6
5 1 4 2 6 3

Output

5

Explanation: Consider the whole array: max = 6, min = 1, range = 5. Any split increases the total because each new segment introduces at least one additional range. For example, splitting after index 3 gives ranges 4 and 4, total 8. Therefore the optimal cost is 5.

Constraints

  • 1 ≤ N ≤ 10^5
  • -10^9 ≤ A[i] ≤ 10^9
  • The answer fits in a signed 64‑bit integer

Optimal Approach & Strategy

Maintain decreasing and increasing monotonic stacks to detect where max/min change, and use a segment tree with lazy propagation to apply the corresponding range updates to dp values, achieving O(N log N).

Brute Force Approach

Enumerate every possible last segment for each position i, compute its range, and take the minimum dp[j‑1] + range for all j ≤ i. This double loop is O(N^2).

Code Solutions

JavaScript Solution
Time: O(N log N)
function solution(nums) {
   let n = nums.length;
   let dp = new Array(n).fill(0).map(() => new Array(n).fill(0));
   for (let i = 0; i < n; i++) {
       dp[i][i] = nums[i];
   }
   for (let len = 2; len <= n; len++) {
       for (let i = 0; i <= n - len; i++) {
           let j = i + len - 1;
           dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]);
       }
   }
   return dp[0][n - 1];
}

Asked in Top Tech Interviews

AppleGoldman Sachs

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.