# Maximize sum of given array after removing valleys

• Difficulty Level : Hard
• Last Updated : 27 Dec, 2021

Given an array arr[] of integers of size N, the task is to maximize the sum of the array after removing valleys from the array when only reducing the value of an element is allowed i.e. the new formed array should not contain any element which has greater value after modification.

Valleys:- An index j is considered as a valley point if  arr[i] > arr[j] and arr[ k ] > arr[ j ]  given that (i < j < k).

Examples

Input : arr[] = { 5, 10, 15 }
Output: 30
Explanation: As array does not contain any valley, so there is no need to reduce any element.

Input : arr[] = { 8, 1, 10, 1, 8 }
Output : 14
Explanation: new_arr=> [1, 1, 10, 1, 1]  and  sum = 14, new_arr can also be constructed as [8, 1, 1, 1, 1], but the sum will be less.

Naive Approach: Consider each element as a peak element and start in decreasing order in both directions of the peak element.

If arr = [8, 1, 10, 1, 8 ]
Consider 10 as peak element and then the final array would like [ 1, 1, 10, 1, 1]

Time Complexity: O(N2)
Auxiliary Space: O(1)

Efficient Approach: Instead of taking each index as a peak point. Calculate prefix and suffix sum array for each index(idx). Prefix array can be used to store the sum of heights from 0 . . . idx satisfying the condition that there is no valley on the left side and idx has the peak element. Suffix sum array also satisfy the same conditions for the suffix of the index idx

The element at an index can span in the left direction, till a smaller element is found, assuming that the current element is the highest one. The next smaller element using stack concept can be used here with minor changes.

• Build the prefix sum (left) and suffix sum (right) array. There will be two case while building the arrays. Consider the cases for prefix sum array below. Same is applicable for suffix sum array also.
1. The current element is the smallest amongst all elements till now.
So, left [ curr_idx ] = ( i +1 ) * arr[i]  . Here (i + 1) denotes the range .
2. There is a smaller element with small_idx, on the left side.
So, left [ curr_idx] = left[ small_idx ] + (current_idx – small_idx) *arr[i]
Using same method  right sum array can be calculated .
• Now, iterate through each index and calculate answer = left[idx] + right[idx] – arr[idx]

Note: arr[idx] is subtracted, because arr[ idx ] is added in left[] as well as right[] array.

See the illustration below for better understanding.

Illustration:

Consider the example  arr[] = { 5, 1, 8 }
While building the prefix sum array
At index = 0: There is no element in the left = 5.
Index = 1: 1 is the smallest among all from the left. So, left = 1 * 2 = 2.
Index = 2: 8 has smaller element 1 at index 1. So left = left + 8*(2 – 1) = 2 + 8 = 10.
So left[] = {5, 2, 10}. Similarly right[] = {7, 2, 8}.
Now while traversing to calculate the answer the values from index 0, 1 and 2 are (5 + 7 – 5), (2 + 2 – 1), (10 + 8 – 8) respectively. The maximum among these is 10. So the answer is 10.

Below is the implementation of the above approach:

## C++

 `// C++ code for the above approach``#include ``using` `namespace` `std;` `// Function to get get the maximum cost``int` `solve(vector<``int``>& arr)``{``  ``int` `n = arr.size();``  ``vector<``int``> left(n, 0);``  ``vector<``int``> right(n, 0);``  ``vector<``int``> stack;` `  ``// Calculate left array``  ``for` `(``int` `i = 0; i < n; i++) {``    ``int` `curr = arr[i];``    ``while` `(stack.size() != 0``           ``&& arr[stack[stack.size() - 1]] >= curr) {``      ``stack.pop_back();``    ``}``    ``// Case 1``    ``if` `(stack.size() == 0)``      ``left[i] = (i + 1) * (arr[i]);` `    ``// Case 2``    ``else` `{``      ``int` `small_idx = stack[stack.size() - 1];``      ``left[i] = left[small_idx]``        ``+ (i - small_idx) * (arr[i]);``    ``}``    ``stack.push_back(i);``  ``}``  ``stack.clear();` `  ``// Calculate suffix sum array``  ``for` `(``int` `i = n - 1; i > -1; i--) {``    ``int` `curr = arr[i];``    ``while` `(stack.size() != 0``           ``&& arr[stack[stack.size() - 1]] >= curr) {``      ``stack.pop_back();``    ``}` `    ``if` `(stack.size() == 0)``      ``right[i] = (n - i) * (arr[i]);` `    ``else` `{``      ``int` `small_idx = stack[stack.size() - 1];``      ``right[i] = right[small_idx]``        ``+ (small_idx - i) * (arr[i]);``    ``}``    ``stack.push_back(i);``  ``}``  ``int` `ans = 0;` `  ``for` `(``int` `i = 0; i < n; i++) {``    ``int` `curr = left[i] + right[i] - arr[i];``    ``ans = max(ans, curr);``  ``}``  ``return` `(ans);``}` `// Driver code``int` `main()``{``  ``vector<``int``> arr = { 5, 1, 8 };``  ``cout << solve(arr);` `  ``return` `0;``}` `// This code is contributed by rakeshsahni`

## Java

 `// Java code for the above approach``import` `java.util.*;``class` `GFG{` `// Function to get get the maximum cost``static` `int` `solve(``int``[] arr)``{``  ``int` `n = arr.length;``  ``int` `[]left = ``new` `int``[n];``  ``int` `[]right = ``new` `int``[n];``  ``Vector stack = ``new` `Vector();` `  ``// Calculate left array``  ``for` `(``int` `i = ``0``; i < n; i++) {``    ``int` `curr = arr[i];``    ``while` `(stack.size() != ``0``           ``&& arr[stack.get(stack.size() - ``1``)] >= curr) {``      ``stack.remove(stack.size() - ``1``);``    ``}``    ``// Case 1``    ``if` `(stack.size() == ``0``)``      ``left[i] = (i + ``1``) * (arr[i]);` `    ``// Case 2``    ``else` `{``      ``int` `small_idx = stack.get(stack.size() - ``1``);``      ``left[i] = left[small_idx]``        ``+ (i - small_idx) * (arr[i]);``    ``}``    ``stack.add(i);``  ``}``  ``stack.clear();` `  ``// Calculate suffix sum array``  ``for` `(``int` `i = n - ``1``; i > -``1``; i--) {``    ``int` `curr = arr[i];``    ``while` `(stack.size() != ``0``           ``&& arr[stack.get(stack.size() - ``1``)] >= curr) {``        ``stack.remove(stack.size() - ``1``);``    ``}` `    ``if` `(stack.size() == ``0``)``      ``right[i] = (n - i) * (arr[i]);` `    ``else` `{``      ``int` `small_idx = stack.get(stack.size() - ``1``);``      ``right[i] = right[small_idx]``        ``+ (small_idx - i) * (arr[i]);``    ``}``    ``stack.add(i);``  ``}``  ``int` `ans = ``0``;` `  ``for` `(``int` `i = ``0``; i < n; i++) {``    ``int` `curr = left[i] + right[i] - arr[i];``    ``ans = Math.max(ans, curr);``  ``}``  ``return` `(ans);``}` `// Driver code``public` `static` `void` `main(String[] args)``{``  ``int``[] arr = { ``5``, ``1``, ``8` `};``  ``System.out.print(solve(arr));` `}``}` `// This code is contributed by 29AjayKumar.`

## Python3

 `# Python code to implement above approach` `# Function to get get the maximum cost``def` `solve(arr):``    ``n ``=` `len``(arr)``    ``left ``=` `[``0``]``*``(n)``    ``right ``=` `[``0``]``*``(n)``    ``stack ``=` `[]` `    ``# Calculate left array``    ``for` `i ``in` `range``(n):``        ``curr ``=` `arr[i]``        ``while``(stack ``and``              ``arr[stack[``-``1``]] >``=` `curr):``            ``stack.pop()` `        ``# Case 1``        ``if` `(``len``(stack) ``=``=` `0``):``            ``left[i] ``=` `(i ``+` `1``)``*``(arr[i])` `        ``# Case 2``        ``else``:``            ``small_idx ``=` `stack[``-``1``]``            ``left[i] ``=` `left[small_idx] \``                     ``+` `(i ``-` `small_idx)``*``(arr[i])``        ``stack.append(i)` `    ``stack.clear()` `    ``# Calculate suffix sum array``    ``for` `i ``in` `range``(n``-``1``, ``-``1``, ``-``1``):``        ``curr ``=` `arr[i]``        ``while``(stack ``and``              ``arr[stack[``-``1``]] >``=` `curr):``            ``stack.pop()` `        ``if` `(``len``(stack) ``=``=` `0``):``            ``right[i] ``=` `(n``-``i)``*``(arr[i])` `        ``else``:``            ``small_idx ``=` `stack[``-``1``]``            ``right[i] ``=` `right[small_idx] \``                     ``+` `(small_idx ``-` `i)``*``(arr[i])` `        ``stack.append(i)` `    ``ans ``=` `0` `    ``for` `i ``in` `range``(n):``        ``curr ``=` `left[i] ``+` `right[i] ``-` `arr[i]``        ``ans ``=` `max``(ans, curr)` `    ``return` `(ans)` `# Driver code``if` `__name__ ``=``=` `"__main__"``:``    ``arr ``=` `[``5``, ``1``, ``8``]``    ``print``(solve(arr))`

## C#

 `// C# code for the above approach``using` `System;``using` `System.Collections.Generic;``class` `GFG {` `  ``// Function to get get the maximum cost``  ``static` `int` `solve(``int``[] arr)``  ``{``    ``int` `n = arr.Length;``    ``int``[] left = ``new` `int``[n];``    ``int``[] right = ``new` `int``[n];``    ``List<``int``> stack = ``new` `List<``int``>();` `    ``// Calculate left array``    ``for` `(``int` `i = 0; i < n; i++) {``      ``int` `curr = arr[i];``      ``while` `(stack.Count != 0``             ``&& arr[stack[stack.Count - 1]] >= curr) {``        ``stack.RemoveAt(stack.Count - 1);``      ``}` `      ``// Case 1``      ``if` `(stack.Count == 0)``        ``left[i] = (i + 1) * (arr[i]);` `      ``// Case 2``      ``else` `{``        ``int` `small_idx = stack[stack.Count - 1];``        ``left[i] = left[small_idx]``          ``+ (i - small_idx) * (arr[i]);``      ``}``      ``stack.Add(i);``    ``}``    ``stack.Clear();` `    ``// Calculate suffix sum array``    ``for` `(``int` `i = n - 1; i > -1; i--) {``      ``int` `curr = arr[i];``      ``while` `(stack.Count != 0``             ``&& arr[stack[stack.Count - 1]] >= curr) {``        ``stack.RemoveAt(stack.Count - 1);``      ``}` `      ``if` `(stack.Count == 0)``        ``right[i] = (n - i) * (arr[i]);` `      ``else` `{``        ``int` `small_idx = stack[stack.Count - 1];``        ``right[i] = right[small_idx]``          ``+ (small_idx - i) * (arr[i]);``      ``}``      ``stack.Add(i);``    ``}``    ``int` `ans = 0;` `    ``for` `(``int` `i = 0; i < n; i++) {``      ``int` `curr = left[i] + right[i] - arr[i];``      ``ans = Math.Max(ans, curr);``    ``}``    ``return` `(ans);``  ``}` `  ``// Driver code``  ``public` `static` `void` `Main(``string``[] args)``  ``{``    ``int``[] arr = { 5, 1, 8 };``    ``Console.WriteLine(solve(arr));``  ``}``}` `// This code is contributed by ukasp.`

## Javascript

 ``
Output
`10`

Time Complexity: O(N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up