Open In App

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

Last Updated : 04 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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: 

  1. Traverse the given array in the range [0, N – 1].
  2. 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.
  3. For each index j update arr[j] as min(arr[j], b[j-1]), where i + 1 <= j < N.
  4. Calculate the maximum sum from each generated b[].
  5. 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>


Output: 

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>


Output: 

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)



Previous Article
Next Article

Similar Reads

Maximize the cost of reducing array elements
Given an array arr[] of N positive integers. We can choose any one index(say K) of the array and reduce all the elements of the array from index 0 to K - 1 by 1. The cost of this operation is K. If at any index(say idx) element is reduced to 0 then we can't perform this operation in the range [idx, N]. The task is to maximize the cost of reduced op
6 min read
Maximize the minimum element of Array by reducing elements one by one
Given an array arr[] containing N integers. In each operation, a minimum integer is chosen from the array and deleted from the array after subtracting it from the remaining elements. The task is to find the maximum of minimum values of the array after any number of such operations. Examples: Input: arr[] = {-1, -2, 4, 3, 5}Output: 4Explanation: Fol
6 min read
Find a Symmetric matrix of order N that contain integers from 0 to N-1 and main diagonal should contain only 0's
Given an integer N. The task is to generate a symmetric matrix of order N*N having the following properties. Main diagonal should contain only 0'sThe matrix should contain elements from 0 to N-1 only. Examples: Input: N = 4 Output: 0 2 3 1 2 0 1 3 3 1 0 2 1 3 2 0Input: N = 5 Output: 0 2 3 4 1 2 0 4 1 3 3 4 0 2 1 4 1 2 0 3 1 3 1 3 0 Approach: Since
10 min read
Make all array elements equal by reducing array elements to half minimum number of times
Given an array arr[] consisting of N integers, the task is to minimize the number of operations required to make all array elements equal by converting Ai to Ai / 2. in each operation Examples: Input: arr[] = {3, 1, 1, 3}Output: 2Explanation: Reducing A0 to A0 / 2 modifies arr[] to {1, 1, 1, 3}. Reducing A3 to A3 / 2 modifies arr[] to {1, 1, 1, 1}.
6 min read
Create a Tree of numbers [1, N] following K triplets (A, B, C) such that any path from A to C cannot contain B
Given an integer N representing numbers [1, N] and K restrictions in the form of triplets {A, B, C}, such that any simple path from A to C cannot contain B. The task is to create a Tree of numbers [1, N] following these K restrictions and print the edges of that tree. Assume that the tree always exists for the given set of restrictions. Examples: I
6 min read
Check if sum of the given array can be reduced to 0 by reducing array elements by K
Given an array arr[] consisting of N integers and an integer K, the task is to check if the sum of the array can be reduced to 0 by subtracting array elements by K any number of times. Examples: Input: arr[ ]= {-3, 2, -1, 5, 1}, K=2Output: "Yes"Explanation: Sum of the array is 4. Therefore, decreasing two elements at any index by K( = 2), makes the
5 min read
Check if all array elements can be reduced to 0 by repeatedly reducing pairs of consecutive elements by their minimum
Given an array arr[] consisting of N integers, the task is to check if it is possible to reduce the array elements to 0 by repeatedly subtracting the minimum of any pair of consecutive array elements from both the elements in the pair. If it is possible, then print "Yes". Otherwise, print "No". Examples: Input: arr[] = {2, 3, 3, 4, 2}Output: YesExp
10 min read
Maximize count of sheets possible by repeatedly reducing its area to half
Given two integers A and B, representing the length and the breadth of a sheet, the task is to find the maximum number of sheets that can be generated from it by repeatedly reducing the area to half until it is not divisible by 2. Examples: Input: A = 5, B = 10Output: 2Explanation: Initial Area = 5 * 10. Count = 0.Area / 2 = 5 * 5. Count = 2. Input
4 min read
Maximize the value left after reducing the Arrays based on given conditions
Given three arrays arr1[], arr2[] and arr3[] of integers, the task is to find the maximum value left in an array after performing the following operation, where in each operation: Select an element (y) from one array and remove that from the array.Subtract y from another element(x) of another array. Note: If there are multiple occurrences of these
8 min read
Minimize cost for reducing array by replacing two elements with sum at most K times for any index
Given an array arr[] of size N and an integer K. The task is to find the minimum cost required to collect the sum of the array. The sum of the array is collected by picking any element and adding it to an element of any index in the array. The addition of elements at the same index is allowed for at most K times. Example: Input: arr[] = {3, 6, 4, 1
11 min read