📌  相关文章
📜  <html>通过减少数组元素以不包含三元组(i,j,k)来最大化数组总和,其中a [i] &lt;a [j]和a [i] &lt;a [k]和j

📅  最后修改于: 2021-05-13 22:29:30             🧑  作者: Mango

给定一个由N个整数组成的数组arr [] ,任务是查找通过将数组元素减少1任意次数(可能为零)而形成的数组的最大和,这样就不会出现三元组(i,j,k) (基于1的索引),使得arr [j]> arr [i]arr [k]> arr [i] ,其中1≤j 。执行减量操作后,还要打印结果数组。

例子:

天真的方法:这个想法是要增加或减少或先增加然后减少的更新数组,以获取更新后所有数组元素的最大和。请按照以下步骤解决问题:

  1. [0,N – 1]范围内遍历给定数组。
  2. 对于每个索引j,将arr [j]更新为min(arr [j],b [j + 1]) ,其中b []存储遵循所需条件且0 <= j 临时数组。
  3. 对于每个索引j,将arr [j]更新为min(arr [j],b [j-1]) ,其中i + 1 <= j
  4. 计算每个生成的b []的最大和。
  5. 打印具有最大和的数组b []

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
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 temperory array when
    // element at index i is peak
    // c stroes final array
    vector 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 temperory array when
  // element at index i is peak
  // c stroes 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 temperory array when
    # element at index i is peak
    # c stroes 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 temperory array when
    // element at index i is peak
    // c stroes 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


C++
// C++ program for the above approach
 
#include 
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;
 
    // Recurr from l to m
    built(l, m, 2 * index, a);
 
    // Recurr 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;
 
    // Recurr for the left
    int d1 = query(l, r, s, m,
                2 * index, a);
 
    // Recurr 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);
 
    // Recurr 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);
 
    // Recurr 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;
 
    // Recurr from l to m
    built(l, m, 2 * index, a);
 
    // Recurr 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;
 
    // Recurr for the left
    int d1 = query(l, r, s, m,
                2 * index, a);
 
    // Recurr 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);
 
    // Recurr 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);
 
    // Recurr 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)
 
    # Recurr from l to m
    built(l, m, 2 * index, a)
 
    # Recurr 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)
 
    # Recurr for the left
    d1 = query(l, r, s, m,
               2 * index, a)
 
    # Recurr 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)
     
    # Recurr 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))
 
    # Recurr 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;
 
// Recurr from l to m
built(l, m, 2 * index, a);
 
// Recurr 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;
 
// Recurr for the left
int d1 = query(l, r, s, m,
                2 * index, a);
 
// Recurr 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);
 
// Recurr 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);
 
// Recurr 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


输出:
Sum = 9
Final Array = 1 1 1 1 1 3 1

时间复杂度: O(N 2 ),其中N是给定数组大小。
辅助空间: O(N)

高效的方法:想法是使用段树来有效地解决此问题。请按照以下步骤解决以上问题:

  • 创建一个细分树,该树返回范围为[l,r]的最小元素的索引。
  • [l,r]中搜索最小的元素。假设它在minindex处
  • 然后进行2次递归调用:
    • 假设所有arr [l …. minindex]都已更改为arr [minindex] 。因此,所有值的总和由下式给出:
  • 然后对[minindex + 1,r]进行递归调用并将所有arr [minindex + 1,r]更改为arr [minindex] 。因此,所有值的总和由下式给出:
  • 在基本情况下,如果l == r ,则当l或r为峰值时,它是阵列的最终总和。
  • 然后,只需找到最佳峰,即具有最大值的峰。
  • 找到最佳峰后,打印阵列及其总和。

下面是上述方法的实现:

C++

// C++ program for the above approach
 
#include 
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;
 
    // Recurr from l to m
    built(l, m, 2 * index, a);
 
    // Recurr 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;
 
    // Recurr for the left
    int d1 = query(l, r, s, m,
                2 * index, a);
 
    // Recurr 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);
 
    // Recurr 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);
 
    // Recurr 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;
 
    // Recurr from l to m
    built(l, m, 2 * index, a);
 
    // Recurr 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;
 
    // Recurr for the left
    int d1 = query(l, r, s, m,
                2 * index, a);
 
    // Recurr 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);
 
    // Recurr 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);
 
    // Recurr 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)
 
    # Recurr from l to m
    built(l, m, 2 * index, a)
 
    # Recurr 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)
 
    # Recurr for the left
    d1 = query(l, r, s, m,
               2 * index, a)
 
    # Recurr 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)
     
    # Recurr 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))
 
    # Recurr 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;
 
// Recurr from l to m
built(l, m, 2 * index, a);
 
// Recurr 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;
 
// Recurr for the left
int d1 = query(l, r, s, m,
                2 * index, a);
 
// Recurr 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);
 
// Recurr 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);
 
// Recurr 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
输出:
Sum = 9
Final Array = 1 1 1 1 1 3 1

时间复杂度: O(N * logN),其中N是给定数组的大小。
辅助空间: O(N)