Algorithm

Sum of Subarray Minimums

Monotonic Stack Pattern

Sum of Subarray Minimums

Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Since the answer may be large, return the answer modulo 10⁹ + 7.

CONSTRAINTS
  • 1 <= arr.length <= 3 × 10⁴
  • 1 <= arr[i] <= 3 × 10⁴
EXAMPLE 1
Input: arr = [3,1,2,4]
Output: 17
Subarrays: [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]. Mins: 3,1,2,4,1,1,2,1,1,1. Sum = 17.
What should we used for the neighbors if they don't exist?
To simplify the math, we imagine virtual neighbors at index -1 and index N that are smaller than every possible value in the array.

Adding up the minimum of every subarray looks like it demands you visit every subarray — and there are about N²/2 of them, so the straightforward double loop is O(N²), far too slow at N = 30,000. The way out is to flip the question. Instead of "what is the minimum of this subarray?", ask of each element: "in how many subarrays am I the minimum?" If a value v is the minimum of exactly c subarrays, it contributes v · c to the total. Sum that across all elements and you're finished — no subarray ever enumerated.

So fix an element at index i and count the subarrays it rules. It's the minimum precisely over the stretch of neighbors that are all bigger than it: extend left until you hit a smaller value, extend right until you hit a smaller value. Say it can reach L positions to the left (counting itself) and R to the right (counting itself). Then a subarray has this element as its minimum exactly when it starts at one of those L left choices and ends at one of those R right choices — every start/end pair gives a distinct such subarray, so the count is L · R.

One trap: duplicates. In [1, 2, 1] both 1s would each try to claim spans that overlap, double-counting the subarrays containing both. The cure is to make the wall strict on one side only: treat a strictly-smaller element as the wall on the left, but a smaller-or-equal element as the wall on the right. That way, among equal minimums, exactly one owns each subarray and nothing is counted twice.

What each side needs is the nearest smaller element to the left and to the right — a nearest-smaller-neighbor query, which is the bread and butter of a monotonic stack: a push/pop stack whose values we keep increasing from bottom to top. In the left pass, for each i we pop every top whose value is bigger than arr[i]; whatever remains on top is the nearest strictly-smaller element to the left. The right pass mirrors it, popping on >= so ties resolve to the right.

python
def sum_subarray_mins(arr):
    MOD = 10**9 + 7
    n = len(arr)
    prev_less = [-1] * n         # nearest strictly-smaller index to the left
    next_less = [n] * n          # nearest smaller-or-equal index to the right

    stack = []
    for i in range(n):
        while stack and arr[stack[-1]] > arr[i]:
            stack.pop()
        prev_less[i] = stack[-1] if stack else -1
        stack.append(i)

    stack = []
    for i in range(n - 1, -1, -1):
        while stack and arr[stack[-1]] >= arr[i]:   # >= sends ties rightward
            stack.pop()
        next_less[i] = stack[-1] if stack else n
        stack.append(i)

    total = 0
    for i in range(n):
        left = i - prev_less[i]         # L choices for the start
        right = next_less[i] - i        # R choices for the end
        total = (total + arr[i] * left * right) % MOD
    return total

Each pass pushes and pops every index once, so three linear sweeps replace the quadratic scan.

Worked Example:[3, 1, 2]
- 3 (idx 0): wall-left at -1, wall-right at idx 1 → L=1, R=1 → 1 subarray → 3 × 1 = 3
- 1 (idx 1): nothing smaller either side → L=2, R=2 → 4 subarrays → 1 × 4 = 4
- 2 (idx 2): wall-left at idx 1, wall-right off the end → L=1, R=1 → 1 subarray → 2 × 1 = 2
- Total: 3 + 4 + 2 = 9.
Interactive Strategy Visualization
CONTRIBUTION ANALYSIS ENGINE

Monotonic Stack Range Strategy

3
1
2
4

Mental Model

  • Contribution: Instead of summing subarrays (O(N²)), we ask: "How many subarrays is index `i` the minimum of?"
  • Expansion: We look left and right for nearest smaller elements using a Monotonic Stack.
LOGICSTEP 1/6
For each element, we find the range where it is the minimum.
STRATEGY

Avoid Double Counting

To handle duplicates, use ">" on one side and ">=" on the other. This ensures each subarray is assigned exactly one minimum index.

O(N²) Brute Force
O(N) Monotonic Stack