Input: nums =[1,2,3]Output: 4Explanation: The 6 subarrays of nums are the following:[1], range = largest - smallest =1-1=0[2], range =2-2=0[3], range =3-3=0[1,2], range =2-1=1[2,3], range =3-2=1[1,2,3], range =3-1=2So the sum of all ranges is0+0+0+1+1+2=4.
Input: nums =[1,3,3]Output: 4Explanation: The 6 subarrays of nums are the following:[1], range = largest - smallest =1-1=0[3], range =3-3=0[3], range =3-3=0[1,3], range =3-1=2[3,3], range =3-3=0[1,3,3], range =3-1=2So the sum of all ranges is0+0+0+2+0+2=4.
For each subarray, the range is the difference between the maximum and minimum. Instead of brute force, we can count for each element how many subarrays it is the maximum and how many it is the minimum, and sum up their contributions. This can be done efficiently using monotonic stacks.
For each index, find the previous and next less/greater elements. The number of subarrays where nums[i] is the minimum is (i - prev_less) * (next_less - i), and similarly for maximum. The answer is the sum of all contributions as maximum minus the sum as minimum.
#include<vector>#include<stack>usingnamespace std;
classSolution {
public:longlong subArrayRanges(vector<int>& nums) {
int n = nums.size();
longlong res =0;
// Max contribution
stack<int> st;
for (int i =0; i <= n; ++i) {
while (!st.empty() && (i == n || nums[st.top()] < (i < n ? nums[i] : INT_MAX))) {
int j = st.top(); st.pop();
int k = st.empty() ?-1: st.top();
res += (longlong)nums[j] * (j - k) * (i - j);
}
st.push(i);
}
// Min contribution
st = stack<int>();
for (int i =0; i <= n; ++i) {
while (!st.empty() && (i == n || nums[st.top()] > (i < n ? nums[i] : INT_MIN))) {
int j = st.top(); st.pop();
int k = st.empty() ?-1: st.top();
res -= (longlong)nums[j] * (j - k) * (i - j);
}
st.push(i);
}
return res;
}
};
import java.util.*;
classSolution {
publiclongsubArrayRanges(int[] nums) {
int n = nums.length;
long res = 0;
Deque<Integer> st =new ArrayDeque<>();
// Max contributionfor (int i = 0; i <= n; ++i) {
while (!st.isEmpty() && (i == n || nums[st.peek()]< (i < n ? nums[i] : Integer.MAX_VALUE))) {
int j = st.pop();
int k = st.isEmpty() ?-1 : st.peek();
res += (long)nums[j]* (j - k) * (i - j);
}
st.push(i);
}
st.clear();
// Min contributionfor (int i = 0; i <= n; ++i) {
while (!st.isEmpty() && (i == n || nums[st.peek()]> (i < n ? nums[i] : Integer.MIN_VALUE))) {
int j = st.pop();
int k = st.isEmpty() ?-1 : st.peek();
res -= (long)nums[j]* (j - k) * (i - j);
}
st.push(i);
}
return res;
}
}
classSolution {
funsubArrayRanges(nums: IntArray): Long {
val n = nums.size
var res = 0Lval st = ArrayDeque<Int>()
// Max contribution
for (i in0..n) {
while (st.isNotEmpty() && (i == n || nums[st.last()] < if (i < n) nums[i] elseInt.MAX_VALUE)) {
val j = st.removeLast()
val k = if (st.isEmpty()) -1else st.last()
res += nums[j].toLong() * (j - k) * (i - j)
}
st.addLast(i)
}
st.clear()
// Min contribution
for (i in0..n) {
while (st.isNotEmpty() && (i == n || nums[st.last()] > if (i < n) nums[i] elseInt.MIN_VALUE)) {
val j = st.removeLast()
val k = if (st.isEmpty()) -1else st.last()
res -= nums[j].toLong() * (j - k) * (i - j)
}
st.addLast(i)
}
return res
}
}
classSolution:
defsubArrayRanges(self, nums: list[int]) -> int:
n = len(nums)
res =0 st = []
# Max contributionfor i in range(n+1):
while st and (i == n or nums[st[-1]] < (nums[i] if i < n else float('inf'))):
j = st.pop()
k = st[-1] if st else-1 res += nums[j] * (j - k) * (i - j)
st.append(i)
st.clear()
# Min contributionfor i in range(n+1):
while st and (i == n or nums[st[-1]] > (nums[i] if i < n else float('-inf'))):
j = st.pop()
k = st[-1] if st else-1 res -= nums[j] * (j - k) * (i - j)
st.append(i)
return res
impl Solution {
pubfnsub_array_ranges(nums: Vec<i32>) -> i64 {
let n = nums.len();
letmut res =0i64;
letmut st = Vec::new();
// Max contribution
for i in0..=n {
whilelet Some(&j) = st.last() {
if i == n || nums[j] <if i < n { nums[i] } else { i32::MAX } {
st.pop();
let k =*st.last().unwrap_or(&-1);
res += nums[j] asi64* (j asi64- k asi64) * (i asi64- j asi64);
} else { break; }
}
st.push(i asi32);
}
st.clear();
// Min contribution
for i in0..=n {
whilelet Some(&j) = st.last() {
if i == n || nums[j] >if i < n { nums[i] } else { i32::MIN } {
st.pop();
let k =*st.last().unwrap_or(&-1);
res -= nums[j] asi64* (j asi64- k asi64) * (i asi64- j asi64);
} else { break; }
}
st.push(i asi32);
}
res
}
}