给定一个由N个整数组成的数组arr [] ,任务是查找通过将数组元素减少1任意次数(可能为零)而形成的数组的最大和,这样就不会出现三元组(i,j,k) (基于1的索引),使得arr [j]> arr [i]和arr [k]> arr [i] ,其中1≤j 。执行减量操作后,还要打印结果数组。
例子:
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}
天真的方法:这个想法是要增加或减少或先增加然后减少的更新数组,以获取更新后所有数组元素的最大和。请按照以下步骤解决问题:
- 在[0,N – 1]范围内遍历给定数组。
- 对于每个索引j,将arr [j]更新为min(arr [j],b [j + 1]) ,其中b []存储遵循所需条件且0 <= j 临时数组。
- 对于每个索引j,将arr [j]更新为min(arr [j],b [j-1]) ,其中i + 1 <= j
。 - 计算每个生成的b []的最大和。
- 打印具有最大和的数组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] 。因此,所有值的总和由下式给出:
arr[minindex]*(minindex – l+1)
- 然后对[minindex + 1,r]进行递归调用,并将所有arr [minindex + 1,r]更改为arr [minindex] 。因此,所有值的总和由下式给出:
arr[minindex]*(r – minindex + 1)
- 在基本情况下,如果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)