The min-product of an array is equal to the minimum value in the array multiplied by the array’s sum.
For example, the array [3,2,5] (minimum value is 2) has a min-product of 2 _ (3+2+5) = 2 _ 10 = 20.
Given an array of integers nums, return the maximum min-product of any non-empty subarray of nums. Since the answer may be large, return it modulo 109 + 7.
Note that the min-product should be maximized before performing the modulo operation. Testcases are generated such that the maximum min-product without modulo will fit in a 64-bit signed integer.
A subarray is a contiguous part of an array.
Example 1:
Input: nums = [1,2,3,2]
Output: 14
Explanation: The maximum min-product is achieved with the subarray [2,3,2] (minimum value is 2).
2 _ (2+3+2) = 2 _ 7 = 14.
Example 2:
Input: nums = [2,3,3,1,2]
Output: 18
Explanation: The maximum min-product is achieved with the subarray [3,3] (minimum value is 3).
3 _ (3+3) = 3 _ 6 = 18.
Example 3:
Input: nums = [3,1,5,6,4,2]
Output: 60
Explanation: The maximum min-product is achieved with the subarray [5,6,4] (minimum value is 4).
4 _ (5+6+4) = 4 _ 15 = 60.
Constraints:
- 1 <= nums.length <= 105
- 1 <= nums[i] <= 107
- 对于包括 nums[i]在内的,并且 nums[i]在其中为最小值的 subarray, 计算 min-product
- 用 monostack 来存储已经遍历过的 num 及其 index, 方便查找距离当前 num[i]最近且小于 num[i]的元素的 index, 这样就可以确定 nums[i]为最小值的 subarray 的左右边界
impl Solution {
pub fn max_sum_min_product(nums: Vec<i32>) -> i32 {
let mut left_bounds = Vec::new();
let mut right_bounds = Vec::new();
let mut stack: Vec<(i32, usize)> = Vec::new();
for i in 0..nums.len() {
while !stack.is_empty() {
let (last, j) = stack.remove(stack.len() - 1);
if last >= nums[i] {
continue;
}
stack.push((last, j));
break;
}
if stack.is_empty() {
left_bounds.push(0);
} else {
left_bounds.push(stack.last().unwrap().1 + 1);
}
stack.push((nums[i], i));
}
stack.clear();
for i in (0..nums.len()).rev() {
while !stack.is_empty() {
let (last, j) = stack.remove(stack.len() - 1);
if last >= nums[i] {
continue;
}
stack.push((last, j));
break;
}
if stack.is_empty() {
right_bounds.push(nums.len() - 1);
} else {
right_bounds.push(stack.last().unwrap().1 - 1);
}
stack.push((nums[i], i));
}
right_bounds.reverse();
let mut ans = 0i64;
let mut prefix: Vec<i64> = nums
.iter()
.scan(0i64, |s, v| {
*s += *v as i64;
Some(*s)
})
.collect();
prefix.insert(0, 0);
for i in 0..nums.len() {
let left = left_bounds[i];
let right = right_bounds[i];
ans = ans.max((prefix[right + 1] - prefix[left]) * nums[i] as i64);
}
(ans % (10i64.pow(9) + 7)) as i32
}
}