Sum of Subarray Minimums

medium array dp stack monotonic stack

Problem

Return the sum of min(subarray) over all contiguous subarrays of arr, modulo 10^9 + 7.

Inputarr = [3,1,2,4]
Output17
Each value contributes value × (#subarrays it dominates) — use a monotonic stack.

def sumSubarrayMins(arr):
    MOD = 10**9 + 7
    n = len(arr)
    left, right = [0]*n, [0]*n
    st = []
    for i in range(n):
        while st and arr[st[-1]] > arr[i]: st.pop()
        left[i] = i + 1 if not st else i - st[-1]
        st.append(i)
    st.clear()
    for i in range(n - 1, -1, -1):
        while st and arr[st[-1]] >= arr[i]: st.pop()
        right[i] = n - i if not st else st[-1] - i
        st.append(i)
    total = 0
    for i in range(n):
        total = (total + arr[i] * left[i] * right[i]) % MOD
    return total
function sumSubarrayMins(arr) {
  const MOD = 1_000_000_007n;
  const n = arr.length;
  const left = new Array(n).fill(0), right = new Array(n).fill(0);
  const st = [];
  for (let i = 0; i < n; i++) {
    while (st.length && arr[st[st.length - 1]] > arr[i]) st.pop();
    left[i] = st.length ? i - st[st.length - 1] : i + 1;
    st.push(i);
  }
  st.length = 0;
  for (let i = n - 1; i >= 0; i--) {
    while (st.length && arr[st[st.length - 1]] >= arr[i]) st.pop();
    right[i] = st.length ? st[st.length - 1] - i : n - i;
    st.push(i);
  }
  let total = 0n;
  for (let i = 0; i < n; i++) total = (total + BigInt(arr[i]) * BigInt(left[i]) * BigInt(right[i])) % MOD;
  return Number(total);
}
class Solution {
    public int sumSubarrayMins(int[] arr) {
        final long MOD = 1_000_000_007L;
        int n = arr.length;
        int[] left = new int[n], right = new int[n];
        Deque<Integer> st = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            while (!st.isEmpty() && arr[st.peek()] > arr[i]) st.pop();
            left[i] = st.isEmpty() ? i + 1 : i - st.peek();
            st.push(i);
        }
        st.clear();
        for (int i = n - 1; i >= 0; i--) {
            while (!st.isEmpty() && arr[st.peek()] >= arr[i]) st.pop();
            right[i] = st.isEmpty() ? n - i : st.peek() - i;
            st.push(i);
        }
        long total = 0;
        for (int i = 0; i < n; i++) total = (total + (long)arr[i] * left[i] * right[i]) % MOD;
        return (int)total;
    }
}
int sumSubarrayMins(vector<int>& arr) {
    const long long MOD = 1000000007LL;
    int n = (int)arr.size();
    vector<int> left(n), right(n);
    stack<int> st;
    for (int i = 0; i < n; i++) {
        while (!st.empty() && arr[st.top()] > arr[i]) st.pop();
        left[i] = st.empty() ? i + 1 : i - st.top();
        st.push(i);
    }
    while (!st.empty()) st.pop();
    for (int i = n - 1; i >= 0; i--) {
        while (!st.empty() && arr[st.top()] >= arr[i]) st.pop();
        right[i] = st.empty() ? n - i : st.top() - i;
        st.push(i);
    }
    long long total = 0;
    for (int i = 0; i < n; i++) total = (total + (long long)arr[i] * left[i] * right[i]) % MOD;
    return (int)total;
}
Time: O(n) Space: O(n)