
‘ARR = [3, 2, 1, 3]’, ‘N = 4’
1. Subarrays with ‘1’ as their minimum value: [1], [2,1], [1,3], [3,2,1], [2,1,3], [3,2,1,3]. Sum = 1 + 1 + 1 + 1 + 1 + 1 = 6.
2. Subarrays with ‘2’ as their minimum value: [2], [3,2]. Sum = 2 + 2 = 4.
3. Subarrays with ‘3’ as their minimum value: [3], [3]. Sum = 3 + 3 = 6.
The sum over all subarrays is ‘6 + 4 + 6 = 16’. Thus, you should return ‘16’ as the answer.
1. The answer may be huge, so return the answer modulo ‘10^9 + 7’.
2. You do not need to print anything; it has already been taken care of. Just implement the function.
The first line of input contains an integer ‘T’ which denotes the number of test cases. Then, the ‘T’ test cases follow.
The first line of each test case contains an integer ‘N’ denoting the size of the array ‘ARR’.
The second line of each test case contains ‘N’ integers representing the array ‘ARR’.
For more clarity, please refer to the sample inputs.
For every test case, you should return the sum of the minimum value in ‘SUB’, where ‘SUB’ ranges over every contiguous subarray of ‘ARR.
1 <= T <= 100
1 <= N <= 1000
1 <= Value in each element of ‘ARR’ <= 10^5
Where ‘T’ is the number of test cases, and ‘N’ is the size of the array ‘ARR’.
Time limit: 1 second
A simple approach is to use two nested loops to generate all the possible subarrays. We can use a variable local to the outer loop to track the minimum values of the subarrays generated in the inner loop.
We have two array’s ‘LEFT’ and ‘RIGHT’, such that:
Then, ‘LEFT[i] + 1’ is the number of subarrays ending with ‘ARR[i]’, where ‘ARR[i]’ is the only minimum value. ‘RIGHT[i] + 1’ is the number of subarrays starting with ‘ARR[i]’, where ‘ARR[i]’ is the first minimum value.
The number of subarrays where ‘ARR[i]’ is the first minimum value will be ‘(LEFT[i] + 1) * (RIGHT[i] + 1)’. The final answer will be summation of ‘(ARR[i] * (LEFT[i] + 1) * (RIGHT[i] + 1))’ where ‘i’ ranges from ‘0’ to ‘N-1’.
We can compute the arrays ‘LEFT’ and ‘RIGHT’ efficiently using a stack. Let’s see how to compute the array ‘LEFT’. We traverse ‘ARR’ using ‘i’ that ranges from ‘0’ to ‘N-1’, and for the current index ‘i’, the stack stores the indexes from ‘0’ to ‘i-1’. The stack doesn’t store all the values from ‘0’ to ‘i-1’. The bottom of the stack is the index of the rightmost smallest value from ‘0’ to ‘i - 1’, let’s say ‘j’. The value above it is the index of the rightmost smallest value from ‘j+1’ to ‘i-1’, and so on. If ‘ARR[i]’ is greater than the top of the stack then ‘LEFT[i] = 1’. Otherwise, if ‘ARR[i]’ is smaller than the top of the stack (let’s say index ‘j’), then it is also smaller than the indexes from ‘j - LEFT[j]’ to ‘j’, so ‘LEFT[i] = LEFT[j] + 1’. Now, pop ‘j’ from the stack. But, if ‘ARR[i]’ is still smaller than the top of the stack, then it is also smaller than the indexes from ‘j - LEFT[j]’ to ‘j’ (‘j’ being the top of the stack). So, ‘LEFT[i] += LEFT[j] + 1’. So, pop all the elements greater than ‘ARR[i]’ from the stack. After that, push ‘i’ to the stack and continue this process until ‘i’ is not equal to ‘N’.
Consider the following example that illustrates how to compute the array ‘LEFT’:
‘ARR = [20, 10, 20, 30, 10]’
Here, ‘LEFT = [0, 1, 0, 0, 2]’
Similarly, we can compute the array ‘RIGHT’. For computing ‘RIGHT’, traverse the array in reverse and pop the stack even when ‘ARR[i]’ is equal to the top of the stack.
In the previous approach, while computing the ‘LEFT’ array, the index ‘i’ which pops the top of the stack (let’s say index ‘j’) such that ‘ARR[i] < ARR[j]’ can give us the value of ‘RIGHT[j] + 1’, which will be ‘i - j’. Similarly, the index below the index ‘j’ in the stack can give us the value of ‘LEFT[j] + 1’. Pop ‘j’ from the stack and let ‘k’ be the current top of stack, so ‘LEFT[j] + 1 = j - k’ (if stack is empty set ‘k = -1’ not ‘0’, as we have to find ‘LEFT[j] + 1’). The contribution of ‘j’ to the final answer will be ‘ARR[j] * (i - j) * (j - k)’ (proved in the previous approach).
Some previous indexes might still be remaining in the stack along with the last index, ‘N-1’ (which is at the top), so we have to compute their contribution to the final answer separately. For that use ‘i = N’, this is a boundary case similar to using ‘k = -1’ for an empty stack.