Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Since the answer may be large, return the answer modulo .
Example 1
Input: arr = [3,1,2,4]
Output: 17
Explanation:
Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].
Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1.
Sum is 17.
Example 2
Input: arr = [11,81,94,43,3]
Output: 444
Constraints
- <= arr.length <=
- <= arr[i] <=
Solution
二重循环遍历,滑动窗口,不出所料超时。
class Solution {
public:
int sumSubarrayMins(vector<int>& arr) {
int n = arr.size();
int left, right;
int sum = 0;
for (left = 0; left < n; left++) {
int min = arr[left];
for (right = left; right < n; right++) {
if (arr[right] < min) min = arr[right];
sum += min % ((int)1e9 + (int)7);
sum %= (int)1e9 + (int)7;
}
}
return sum;
}
};
为何超时?题目中最大为 , 已接近 且有 MOD 运算,因此必然会超时。
题解:单调栈
class Solution {
public:
int sumSubarrayMins(vector<int>& arr) {
int n = arr.size();
vector<int> monoStack;
vector<int> left(n), right(n);
for (int i = 0; i < n; i++) {
while (!monoStack.empty() && arr[monoStack.back()] > arr[i]) {
monoStack.pop_back();
}
if (monoStack.empty()) {
left[i] = i + 1;
} else {
left[i] = i - monoStack.back();
}
monoStack.push_back(i);
}
monoStack.clear();
for (int i = n - 1; i >= 0; i--) {
while (!monoStack.empty() && arr[monoStack.back()] >= arr[i]) {
monoStack.pop_back();
}
if (monoStack.empty()) {
right[i] = n - i;
} else {
right[i] = monoStack.back() - i;
}
monoStack.push_back(i);
}
long long ans = 0;
for (int i = 0; i < n; i++) {
ans = (ans + (long long)arr[i] * left[i] * right[i]) % 1000000007;
}
return ans;
}
};
注意判断左右边界的循环条件不能同时闭区间,不然左右会重复算。