class Solution {
public long subArrayRanges(int[] nums) {
return sumSubarrayMaxs(nums) - sumSubarrayMins(nums);
}
private long sumSubarrayMins(int[] arr) {
int n = arr.length;
int[] left = new int[n];
int[] right = new int[n];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) {
stack.pop();
}
left[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
stack.clear();
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) {
stack.pop();
}
right[i] = stack.isEmpty() ? n : stack.peek();
stack.push(i);
}
long result = 0;
for (int i = 0; i < n; i++) {
long leftCount = i - left[i];
long rightCount = right[i] - i;
result += (long) arr[i] * leftCount * rightCount;
}
return result;
}
private long sumSubarrayMaxs(int[] arr) {
int n = arr.length;
int[] left = new int[n];
int[] right = new int[n];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
stack.pop();
}
left[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
stack.clear();
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && arr[stack.peek()] <= arr[i]) {
stack.pop();
}
right[i] = stack.isEmpty() ? n : stack.peek();
stack.push(i);
}
long result = 0;
for (int i = 0; i < n; i++) {
long leftCount = i - left[i];
long rightCount = right[i] - i;
result += (long) arr[i] * leftCount * rightCount;
}
return result;
}
}