You can do this in O(n) time and space.
The technique is to use the algorithm for all nearest smaller values. First, break the problem into two parts:
- Find the sum of all subarray maximums
- Find the sum of all subarray minimums, and subtract this from the first sum.
The solution for both problems is identical apart from exchanging all occurrences of 'less than' with 'greater than', so I'll describe the minimums case only.
For each element A[i] of the array, you can ask: 'How many subarrays have A[i] as their minimum element?' To deal with duplicates, assume we always take the rightmost occurrence of a minimum element within a subarray as the 'representative' element.
The question transforms to finding how far to the left of A[i] we can go before seeing an element strictly smaller than A[i], and how far to the right of A[i] we can go before seeing an element as small as A[i]. Multiply these two distances to get all possible choices of left and right endpoints among subarrays that have A[i] as their minimum element. We can find both of these directly with the 'all nearest smaller values' algorithm, and solve the rest of the problem like so (pseudocode):
1. For each position i in the array A, let previous_smaller[i]
be the largest index j such that A[j] < A[i] and 0 <= j < i,
or -1 if there is no such index.
2. For each position i in the array A, let next_smaller_or_equal[i]
be the smallest index j such that A[j] <= A[i] and i < j < n,
or n if there is no such index.
3. Return the sum over all i, 0 <= i < n, of
(A[i] *
(next_larger_or_equal[i] - i) *
(i - previous_larger[i]))
There are several implementations of all nearest smaller values in the answers to this question, for example, and pseudocode in the Wikipedia article. To find 'next smaller values' instead of 'previous smaller values', simply run the algorithm on a reversed array A (or just traverse A in reverse order, from A[n-1] down to A[0]).