Maximize sum of array by reducing array elements to contain no triplets (i, j, k) where a[i] < a[j] and a[i] < a[k] and j <i < k
Given an array arr[] consisting of N integers, the task is to find the maximum sum of an array formed by decreasing array elements by 1 any number of times(possibly zero) such that there are no triplets (i, j, k)( 1-based indexing ) such that arr[j] > arr[i] and arr[k] > arr[i], where 1 ≤ j < i < k ≤ N. Print the resultant array also after performing the decrement operation.
Examples:
Input: arr[] = {1, 2, 1, 2, 1, 3, 1}
Output:
Sum = 9
Final Array = {1, 1, 1, 1, 1, 3, 1}Input: arr[] = {2, 4, 1, 2, 3, 1, 2}
Output:
Sum = 11
Final Array: {2, 4, 1, 1, 1, 1, 1}
Naive Approach: The idea is to update the array either increasing or decreasing or first increasing and then decreasing to get the maximum sum of all the array elements after the update. Follow the below steps to solve the problem:
- Traverse the given array in the range [0, N – 1].
- For each index j update arr[j] as min(arr[j], b[j+1]), where b[] is storing temporary array which follow the required conditions and 0 <= j < i.
- For each index j update arr[j] as min(arr[j], b[j-1]), where i + 1 <= j < N.
- Calculate the maximum sum from each generated b[].
- Print the array b[] having the maximum sum.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // Function to find and print maximum // sum and corresponding array void maximumSum( int m[], int n) { int cnt = 0, ans = 0; // b stores temporary array when // element at index i is peak // c stores final array vector< int > b(n), c(n); // Check the array for each index for ( int i = 0; i < n; i++) { // Choose m[i] as peak b[i] = m[i]; cnt = b[i]; // Check left for ( int j = i - 1; j >= 0; j--) { b[j] = min(b[j + 1], m[j]); cnt += b[j]; } // Check right for ( int j = i + 1; j < n; j++) { b[j] = min(b[j - 1], m[j]); cnt += b[j]; } // Check if sum is maximum if (ans < cnt) { ans = cnt; // Store the current array for ( int j = 0; j < n; j++) { c[j] = b[j]; } } } // Calculate sum int sum = 0; for ( int i = 0; i < n; i++) { sum += c[i]; } cout << "Sum = " << sum << endl; // Print array cout << "Final Array = " ; for ( int i = 0; i < n; i++) { cout << c[i] << " " ; } } // Drive Code int main() { // Given array int arr[] = { 1, 2, 1, 2, 1, 3, 1 }; int N = sizeof (arr) / sizeof (arr[0]); // Function Call maximumSum(arr, N); return 0; } |
Java
// Java program for // the above approach import java.util.*; class GFG{ // Function to find and print maximum // sum and corresponding array static void maximumSum( int m[], int n) { int cnt = 0 , ans = 0 ; // b stores temporary array when // element at index i is peak // c stores final array int []b = new int [n]; int []c = new int [n]; // Check the array for each index for ( int i = 0 ; i < n; i++) { // Choose m[i] as peak b[i] = m[i]; cnt = b[i]; // Check left for ( int j = i - 1 ; j >= 0 ; j--) { b[j] = Math.min(b[j + 1 ], m[j]); cnt += b[j]; } // Check right for ( int j = i + 1 ; j < n; j++) { b[j] = Math.min(b[j - 1 ], m[j]); cnt += b[j]; } // Check if sum is maximum if (ans < cnt) { ans = cnt; // Store the current array for ( int j = 0 ; j < n; j++) { c[j] = b[j]; } } } // Calculate sum int sum = 0 ; for ( int i = 0 ; i < n; i++) { sum += c[i]; } System.out.print( "Sum = " + sum + "\n" ); // Print array System.out.print( "Final Array = " ); for ( int i = 0 ; i < n; i++) { System.out.print(c[i] + " " ); } } // Drive Code public static void main(String[] args) { // Given array int arr[] = { 1 , 2 , 1 , 2 , 1 , 3 , 1 }; int N = arr.length; // Function Call maximumSum(arr, N); } } // This code is contributed by Princi Singh |
Python3
# Python3 program for the above approach # Function to find and print maximum # sum and corresponding array def maximumSum(m, n): cnt = 0 ans = 0 # b stores temporary array when # element at index i is peak # c stores final array b = [ 0 for i in range (n)] c = [ 0 for i in range (n)] # Check the array for each index for i in range (n): # Choose m[i] as peak b[i] = m[i] cnt = b[i] # Check left for j in range (i - 1 , - 1 , - 1 ): b[j] = min (b[j + 1 ], m[j]) cnt + = b[j] # Check right for j in range (i + 1 , n): b[j] = min (b[j - 1 ], m[j]) cnt + = b[j] # Check if sum is maximum if (ans < cnt): ans = cnt # Store the current array for j in range (n): c[j] = b[j] # Calculate sum and printing print ( "Sum = " , sum (c)) print ( "Final Array = " , * c) # Driver Code arr = [ 1 , 2 , 1 , 2 , 1 , 3 , 1 ] N = len (arr) / / arr[ 0 ] # Function call maximumSum(arr, N) # This code is contributed by dadi madhav |
C#
// C# program for the above approach using System; class GFG{ // Function to find and print maximum // sum and corresponding array static void maximumSum( int []m, int n) { int cnt = 0, ans = 0; // b stores temporary array when // element at index i is peak // c stores readonly array int []b = new int [n]; int []c = new int [n]; // Check the array for each index for ( int i = 0; i < n; i++) { // Choose m[i] as peak b[i] = m[i]; cnt = b[i]; // Check left for ( int j = i - 1; j >= 0; j--) { b[j] = Math.Min(b[j + 1], m[j]); cnt += b[j]; } // Check right for ( int j = i + 1; j < n; j++) { b[j] = Math.Min(b[j - 1], m[j]); cnt += b[j]; } // Check if sum is maximum if (ans < cnt) { ans = cnt; // Store the current array for ( int j = 0; j < n; j++) { c[j] = b[j]; } } } // Calculate sum int sum = 0; for ( int i = 0; i < n; i++) { sum += c[i]; } Console.Write( "Sum = " + sum + "\n" ); // Print array Console.Write( "Final Array = " ); for ( int i = 0; i < n; i++) { Console.Write(c[i] + " " ); } } // Drive Code public static void Main(String[] args) { // Given array int []arr = { 1, 2, 1, 2, 1, 3, 1 }; int N = arr.Length; // Function call maximumSum(arr, N); } } // This code is contributed by Amit Katiyar |
Javascript
<script> // JavaScript program for // the above approach // Function to find and print maximum // sum and corresponding array function maximumSum(m,n) { let cnt = 0, ans = 0; // b stores temporary array when // element at index i is peak // c stores final array let b = new Array(n); let c = new Array(n); // Check the array for each index for (let i = 0; i < n; i++) { // Choose m[i] as peak b[i] = m[i]; cnt = b[i]; // Check left for (let j = i - 1; j >= 0; j--) { b[j] = Math.min(b[j + 1], m[j]); cnt += b[j]; } // Check right for (let j = i + 1; j < n; j++) { b[j] = Math.min(b[j - 1], m[j]); cnt += b[j]; } // Check if sum is maximum if (ans < cnt) { ans = cnt; // Store the current array for (let j = 0; j < n; j++) { c[j] = b[j]; } } } // Calculate sum let sum = 0; for (let i = 0; i < n; i++) { sum += c[i]; } document.write( "Sum = " + sum + "<br>" ); // Print array document.write( "Final Array = " ); for (let i = 0; i < n; i++) { document.write(c[i] + " " ); } } // Drive Code // Given array let arr=[1, 2, 1, 2, 1, 3, 1]; let N = arr.length; // Function Call maximumSum(arr, N); // This code is contributed by unknown2108 </script> |
Sum = 9 Final Array = 1 1 1 1 1 3 1
Time Complexity: O(N2), where N is the size of the given array.
Auxiliary Space: O(N)
Efficient Approach: The idea is to use a Segment Tree to solve this problem efficiently. Follow the below steps to solve the above problem:
- Create a Segment Tree which returns the index of the smallest element in the range [l, r].
- Search for the smallest element in [l, r]. Suppose it is at minindex.
- Then make 2 recursive calls:
- Assuming that all arr[l….minindex] have been changed to arr[minindex]. Therefore, the sum of all values is given by:
arr[minindex]*(minindex – l+1)
- Then make the recursive call on [minindex + 1, r] and change all arr[minindex + 1, r] to arr[minindex]. Therefore, the sum of all values is given by:
arr[minindex]*(r – minindex + 1)
- In the base case, if l==r, then it is the final sum of the array when l or r is peak.
- Then simply find the optimal peak, i.e. the one with maximum value.
- After finding the optimal peak, print the array and its sum.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; int peak, maxi = -1; // For storing segment tree int seg[4 * 500001]; // Initialize segment tree void built( int l, int r, int index, int a[]) { // Base Case if (l == r) { seg[index] = l; return ; } // Get mid int m = l + (r - l) / 2; // Recur from l to m built(l, m, 2 * index, a); // Recur from m+1 to r built(m + 1, r, 2 * index + 1, a); if (a[seg[2 * index]] < a[seg[2 * index + 1]]) seg[index] = seg[2 * index]; else seg[index] = seg[2 * index + 1]; } // Query to find minimum value index // between l and r int query( int l, int r, int s, int e, int index, int a[]) { // If segment is invalid if (s > r || e < l) return -1; // If segment is inside the // desired segment if (s >= l && e <= r) return seg[index]; // Find the mid int m = s + (e - s) / 2; // Recur for the left int d1 = query(l, r, s, m, 2 * index, a); // Recur for the right int d2 = query(l, r, m + 1, e, 2 * index + 1, a); // Update the query if (d1 == -1) return d2; if (d2 == -1) return d1; if (a[d1] < a[d2]) return d1; else return d2; } // Function for finding the optimal peak void optimalPeak( int l, int r, int value, int n, int a[]) { if (l > r) return ; // Check if its the peak if (l == r) { // Update the value for the // maximum sum if (value + a[l] > maxi) { maxi = a[l] + value; peak = l; return ; } return ; } // Index of minimum element in // l and r int indexmini = query(l, r, 0, n - 1, 1, a); int value1 = a[indexmini] * (indexmini - l + 1); // Recur right of minimum index optimalPeak(indexmini + 1, r, value + value1, n, a); // Update the max and peak value if (indexmini + 1 > r) { if (value + value1 > maxi) { maxi = value + value1; peak = indexmini; } } int value2 = a[indexmini] * (r - indexmini + 1); // Recur left of minimum index optimalPeak(l, indexmini - 1, value + value2, n, a); // Update the max and peak value if (l > indexmini - 1) { if (value + value2 > maxi) { maxi = value + value2; peak = l; } } } // Print maximum sum and the array void maximumSum( int a[], int n) { // Initialize segment tree built(0, n - 1, 1, a); // Get the peak optimalPeak(0, n - 1, 0, n, a); // Store the required array int ans[n]; ans[peak] = a[peak]; // Update the ans[] for ( int i = peak + 1; i < n; i++) { ans[i] = min(ans[i - 1], a[i]); } for ( int i = peak - 1; i >= 0; i--) { ans[i] = min(a[i], ans[i + 1]); } // Find the maximum sum int sum = 0; for ( int i = 0; i < n; i++) { sum += ans[i]; } // Print sum and optimal array cout << "Sum = " << sum << endl; cout << "Final Array = " ; for ( int i = 0; i < n; i++) { cout << ans[i] << " " ; } } // Drive Code int main() { // Given array int arr[] = { 1, 2, 1, 2, 1, 3, 1 }; int N = sizeof (arr) / sizeof (arr[0]); // Function Call maximumSum(arr, N); return 0; } |
Java
// Java program for the above approach import java.util.*; class GFG{ static int peak, maxi = - 1 ; // For storing segment tree static int []seg = new int [ 4 * 500001 ]; // Initialize segment tree static void built( int l, int r, int index, int a[]) { // Base Case if (l == r) { seg[index] = l; return ; } // Get mid int m = l + (r - l) / 2 ; // Recur from l to m built(l, m, 2 * index, a); // Recur from m+1 to r built(m + 1 , r, 2 * index + 1 , a); if (a[seg[ 2 * index]] < a[seg[ 2 * index + 1 ]]) seg[index] = seg[ 2 * index]; else seg[index] = seg[ 2 * index + 1 ]; } // Query to find minimum value index // between l and r static int query( int l, int r, int s, int e, int index, int a[]) { // If segment is invalid if (s > r || e < l) return - 1 ; // If segment is inside the // desired segment if (s >= l && e <= r) return seg[index]; // Find the mid int m = s + (e - s) / 2 ; // Recur for the left int d1 = query(l, r, s, m, 2 * index, a); // Recur for the right int d2 = query(l, r, m + 1 , e, 2 * index + 1 , a); // Update the query if (d1 == - 1 ) return d2; if (d2 == - 1 ) return d1; if (a[d1] < a[d2]) return d1; else return d2; } // Function for finding the optimal peak static void optimalPeak( int l, int r, int value, int n, int a[]) { if (l > r) return ; // Check if its the peak if (l == r) { // Update the value for the // maximum sum if (value + a[l] > maxi) { maxi = a[l] + value; peak = l; return ; } return ; } // Index of minimum element in // l and r int indexmini = query(l, r, 0 , n - 1 , 1 , a); int value1 = a[indexmini] * (indexmini - l + 1 ); // Recur right of minimum index optimalPeak(indexmini + 1 , r, value + value1, n, a); // Update the max and peak value if (indexmini + 1 > r) { if (value + value1 > maxi) { maxi = value + value1; peak = indexmini; } } int value2 = a[indexmini] * (r - indexmini + 1 ); // Recur left of minimum index optimalPeak(l, indexmini - 1 , value + value2, n, a); // Update the max and peak value if (l > indexmini - 1 ) { if (value + value2 > maxi) { maxi = value + value2; peak = l; } } } // Print maximum sum and the array static void maximumSum( int a[], int n) { // Initialize segment tree built( 0 , n - 1 , 1 , a); // Get the peak optimalPeak( 0 , n - 1 , 0 , n, a); // Store the required array int []ans = new int [n]; ans[peak] = a[peak]; // Update the ans[] for ( int i = peak + 1 ; i < n; i++) { ans[i] = Math.min(ans[i - 1 ], a[i]); } for ( int i = peak - 1 ; i >= 0 ; i--) { ans[i] = Math.min(a[i], ans[i + 1 ]); } // Find the maximum sum int sum = 0 ; for ( int i = 0 ; i < n; i++) { sum += ans[i]; } // Print sum and optimal array System.out.print( "Sum = " + sum + "\n" ); System.out.print( "Final Array = " ); for ( int i = 0 ; i < n; i++) { System.out.print(ans[i]+ " " ); } } // Drive Code public static void main(String[] args) { // Given array int arr[] = { 1 , 2 , 1 , 2 , 1 , 3 , 1 }; int N = arr.length; // Function Call maximumSum(arr, N); } } // This code contributed by gauravrajput1 |
Python3
# Python3 program for the above approach peak = 0 maxi = - 1 # For storing segment tree seg = [ 0 for i in range ( 4 * 500001 )] # Initialize segment tree def built(l, r, index, a): # Base Case if (l = = r): seg[index] = l return # Get mid m = int (l + (r - l) / 2 ) # Recur from l to m built(l, m, 2 * index, a) # Recur from m+1 to r built(m + 1 , r, 2 * index + 1 , a) if (a[seg[ 2 * index]] < a[seg[ 2 * index + 1 ]]): seg[index] = seg[ 2 * index] else : seg[index] = seg[ 2 * index + 1 ] # Query to find minimum value index # between l and r def query(l, r, s, e, index, a): # If segment is invalid if (s > r or e < l): return - 1 # If segment is inside the # desired segment if (s > = l and e < = r): return seg[index] # Find the mid m = int (s + (e - s) / 2 ) # Recur for the left d1 = query(l, r, s, m, 2 * index, a) # Recur for the right d2 = query(l, r, m + 1 , e, 2 * index + 1 , a) # Update the query if (d1 = = - 1 ): return d2 if (d2 = = - 1 ): return d1 if (a[d1] < a[d2]): return d1 else : return d2 # Function for finding the optimal peak def optimalPeak(l, r, value, n, a): global maxi, peak if (l > r): return # Check if its the peak if (l = = r): # Update the value for the # maximum sum if (value + a[l] > maxi): maxi = a[l] + value peak = l return return # Index of minimum element in # l and r indexmini = query(l, r, 0 , n - 1 , 1 , a) value1 = a[indexmini] * (indexmini - l + 1 ) # Recur right of minimum index optimalPeak(indexmini + 1 , r, value + value1, n, a) # Update the max and peak value if (indexmini + 1 > r): if (value + value1 > maxi): maxi = value + value1 peak = indexmini value2 = (a[indexmini] * (r - indexmini + 1 )) # Recur left of minimum index optimalPeak(l, indexmini - 1 , value + value2, n, a) # Update the max and peak value if (l > indexmini - 1 ): if (value + value2 > maxi): maxi = value + value2 peak = l # Print maximum sum and the array def maximumSum(a, n): # Initialize segment tree built( 0 , n - 1 , 1 , a) # Get the peak optimalPeak( 0 , n - 1 , 0 , n, a) # Store the required array ans = [ 0 for i in range (n)] ans[peak] = a[peak] # Update the ans[] for i in range (peak + 1 , n): ans[i] = min (ans[i - 1 ], a[i]) for i in range (peak - 1 , - 1 , - 1 ): ans[i] = min (a[i], ans[i + 1 ]) # Find the maximum sum Sum = 0 Sum = sum (ans) # Print sum and optimal array print ( "Sum = " , Sum ) print ( "Final Array = " , end = "") print ( * ans, sep = " " ) # Driver Code # Given array arr = [ 1 , 2 , 1 , 2 , 1 , 3 , 1 ] N = len (arr) # Function Call maximumSum(arr, N) # This code is contributed by rag2127 |
C#
// C# program for // the above approach using System; class GFG{ static int peak, maxi = -1; // For storing segment tree static int []seg = new int [4 * 500001]; // Initialize segment tree static void built( int l, int r, int index, int []a) { // Base Case if (l == r) { seg[index] = l; return ; } // Get mid int m = l + (r - l) / 2; // Recur from l to m built(l, m, 2 * index, a); // Recur from m+1 to r built(m + 1, r, 2 * index + 1, a); if (a[seg[2 * index]] < a[seg[2 * index + 1]]) seg[index] = seg[2 * index]; else seg[index] = seg[2 * index + 1]; } // Query to find minimum value index // between l and r static int query( int l, int r, int s, int e, int index, int []a) { // If segment is invalid if (s > r || e < l) return -1; // If segment is inside the // desired segment if (s >= l && e <= r) return seg[index]; // Find the mid int m = s + (e - s) / 2; // Recur for the left int d1 = query(l, r, s, m, 2 * index, a); // Recur for the right int d2 = query(l, r, m + 1, e, 2 * index + 1, a); // Update the query if (d1 == -1) return d2; if (d2 == -1) return d1; if (a[d1] < a[d2]) return d1; else return d2; } // Function for finding the optimal peak static void optimalPeak( int l, int r, int value, int n, int []a) { if (l > r) return ; // Check if its the peak if (l == r) { // Update the value for the // maximum sum if (value + a[l] > maxi) { maxi = a[l] + value; peak = l; return ; } return ; } // Index of minimum element in // l and r int indexmini = query(l, r, 0, n - 1, 1, a); int value1 = a[indexmini] * (indexmini - l + 1); // Recur right of minimum index optimalPeak(indexmini + 1, r, value + value1, n, a); // Update the max and peak value if (indexmini + 1 > r) { if (value + value1 > maxi) { maxi = value + value1; peak = indexmini; } } int value2 = a[indexmini] * (r - indexmini + 1); // Recur left of minimum index optimalPeak(l, indexmini - 1, value + value2, n, a); // Update the max and peak value if (l > indexmini - 1) { if (value + value2 > maxi) { maxi = value + value2; peak = l; } } } // Print maximum sum and the array static void maximumSum( int []a, int n) { // Initialize segment tree built(0, n - 1, 1, a); // Get the peak optimalPeak(0, n - 1, 0, n, a); // Store the required array int []ans = new int [n]; ans[peak] = a[peak]; // Update the ans[] for ( int i = peak + 1; i < n; i++) { ans[i] = Math.Min(ans[i - 1], a[i]); } for ( int i = peak - 1; i >= 0; i--) { ans[i] = Math.Min(a[i], ans[i + 1]); } // Find the maximum sum int sum = 0; for ( int i = 0; i < n; i++) { sum += ans[i]; } // Print sum and optimal array Console.Write( "Sum = " + sum + "\n" ); Console.Write( "Final Array = " ); for ( int i = 0; i < n; i++) { Console.Write(ans[i] + " " ); } } // Drive Code public static void Main(String[] args) { // Given array int []arr = {1, 2, 1, 2, 1, 3, 1}; int N = arr.Length; // Function Call maximumSum(arr, N); } } // This code is contributed by shikhasingrajput |
Javascript
<script> // Javascript program for the above approach let peak, maxi = -1; let seg = new Array(4 * 500001); // Initialize segment tree function built(l,r,index,a) { // Base Case if (l == r) { seg[index] = l; return ; } // Get mid let m = l + Math.floor((r - l) / 2); // Recur from l to m built(l, m, 2 * index, a); // Recur from m+1 to r built(m + 1, r, 2 * index + 1, a); if (a[seg[2 * index]] < a[seg[2 * index + 1]]) seg[index] = seg[2 * index]; else seg[index] = seg[2 * index + 1]; } // Query to find minimum value index // between l and r function query(l,r,s,e,index,a) { // If segment is invalid if (s > r || e < l) return -1; // If segment is inside the // desired segment if (s >= l && e <= r) return seg[index]; // Find the mid let m = s + Math.floor((e - s) / 2); // Recur for the left let d1 = query(l, r, s, m, 2 * index, a); // Recur for the right let d2 = query(l, r, m + 1, e, 2 * index + 1, a); // Update the query if (d1 == -1) return d2; if (d2 == -1) return d1; if (a[d1] < a[d2]) return d1; else return d2; } // Function for finding the optimal peak function optimalPeak(l,r,value,n,a) { if (l > r) return ; // Check if its the peak if (l == r) { // Update the value for the // maximum sum if (value + a[l] > maxi) { maxi = a[l] + value; peak = l; return ; } return ; } // Index of minimum element in // l and r let indexmini = query(l, r, 0, n - 1, 1, a); let value1 = a[indexmini] * (indexmini - l + 1); // Recur right of minimum index optimalPeak(indexmini + 1, r, value + value1, n, a); // Update the max and peak value if (indexmini + 1 > r) { if (value + value1 > maxi) { maxi = value + value1; peak = indexmini; } } let value2 = a[indexmini] * (r - indexmini + 1); // Recur left of minimum index optimalPeak(l, indexmini - 1, value + value2, n, a); // Update the max and peak value if (l > indexmini - 1) { if (value + value2 > maxi) { maxi = value + value2; peak = l; } } } // Print maximum sum and the array function maximumSum(a,n) { // Initialize segment tree built(0, n - 1, 1, a); // Get the peak optimalPeak(0, n - 1, 0, n, a); // Store the required array let ans = new Array(n); ans[peak] = a[peak]; // Update the ans[] for (let i = peak + 1; i < n; i++) { ans[i] = Math.min(ans[i - 1], a[i]); } for (let i = peak - 1; i >= 0; i--) { ans[i] = Math.min(a[i], ans[i + 1]); } // Find the maximum sum let sum = 0; for (let i = 0; i < n; i++) { sum += ans[i]; } // Print sum and optimal array document.write( "Sum = " + sum + "<br>" ); document.write( "Final Array = " ); for (let i = 0; i < n; i++) { document.write(ans[i]+ " " ); } } // Drive Code let arr=[1, 2, 1, 2, 1, 3, 1]; let N = arr.length; // Function Call maximumSum(arr, N); // This code is contributed by patel2127 </script> |
Sum = 9 Final Array = 1 1 1 1 1 3 1
Time Complexity: O(N*logN), where N is the size of the given array.
Auxiliary Space: O(N)
Please Login to comment...