Sum of minimum elements of all subarrays

Given an array A of n integers. The task is to find the sum of minimum of all possible (contiguous) subarray of A.

Examples:

Input: A = [3, 1, 2, 4]
Output: 17
Explanation: Subarrays are [3], [1], [2], [4], [3, 1], [1, 2], [2, 4], [3, 1, 2], [1, 2, 4], [3, 1, 2, 4].
Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17.

Input : A = [1, 2, 3, 4]
Output : 20

Approach: The Naive approach is to generate all possible (contiguous) subarrays, find their minimum and add them to result. The time complexity will be O(N2).

Efficient Approach: The general intuition for solution to the problem is to find sum(A[i] * f(i)), where f(i) is the number of subarrays in which A[i] is the minimum.

In order to find f[i], we need to find out:
left[i], the length of strictly larger numbers on the left of A[i],
right[i], the length of larger numbers on the right of A[i].

We make two arrays left[ ] and right[ ] such that:
left[i] + 1 equals to the number of subarrays ending with A[i], and A[i] is only single minimum.
Similarly, right[i] + 1 equals to the number of subarrays starting with A[i], and A[i] is first minimum.

Finally, f(i) = (left[i]) * (right[i]), where f[i] equals total number of subarrays in which A[i] is minimum.

Below is the implementation of above approach

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP implementation of above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to return required minimum sum
int sumSubarrayMins(int A[], int n)
{
    int left[n], right[n];
  
    stack<pair<int, int> > s1, s2;
  
    // getting number of element strictly larger 
    // than A[i] on Left.
    for (int i = 0; i < n; ++i) {
        int cnt = 1;
  
        // get elements from stack until element 
        // greater than A[i] found
        while (!s1.empty() && (s1.top().first) > A[i]) {
            cnt += s1.top().second;
            s1.pop();
        }
  
        s1.push({ A[i], cnt });
        left[i] = cnt;
    }
  
    // getting number of element larger than A[i] on Right.
    for (int i = n - 1; i >= 0; --i) {
        int cnt = 1;
  
        // get elements from stack until element greater
        // or equal to A[i] found
        while (!s2.empty() && (s2.top().first) >= A[i]) {
            cnt += s2.top().second;
            s2.pop();
        }
  
        s2.push({ A[i], cnt });
        right[i] = cnt;
    }
  
    int result = 0;
  
    // calculating required resultult
    for (int i = 0; i < n; ++i)
        result = (result + A[i] * left[i] * right[i]);
  
    return result;
}
  
// Driver program
int main()
{
    int A[] = { 3, 1, 2, 4 };
  
    int n = sizeof(A) / sizeof(A[0]);
  
    // function call to get required resultult
    cout << sumSubarrayMins(A, n);
  
    return 0;
}
// This code is written by Sanjit_Prasad

chevron_right


Python3

# Python3 implementation of above approach

# Function to return required minimum sum
def sumSubarrayMins(A, n):

left, right = [None] * n, [None] * n

# Use list as stack
s1, s2 = [], []

# getting number of element strictly
# larger than A[i] on Left.
for i in range(0, n):
cnt = 1

# get elements from stack until
# element greater than A[i] found
while len(s1) > 0 and s1[-1][0] > A[i]:
cnt += s1[-1][1]
s1.pop()

s1.append([A[i], cnt])
left[i] = cnt

# getting number of element
# larger than A[i] on Right.
for i in range(n – 1, -1, -1):
cnt = 1

# get elements from stack until
# element greater or equal to A[i] found
while len(s2) > 0 and s2[-1][0] > A[i]:
cnt += s2[-1][1]
s2.pop()

s2.append([A[i], cnt])
right[i] = cnt

result = 0

# calculating required resultult
for i in range(0, n):
result += A[i] * left[i] * right[i]

return result

# Driver Code
if __name__ == “__main__”:

A = [3, 1, 2, 4]
n = len(A)

# function call to get
# required resultult
print(sumSubarrayMins(A, n))

# This code is contributed
# by Rituraj Jain

Output:

17

Time Complexity: O(N), where N is the length of A.
Space Complexity: O(N).



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : rituraj_jain