给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
示例 1:
输入:arr = [3,1,2,4]
输出:17
解释:
子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。
示例 2:
输入:arr = [11,81,94,43,3]
输出:444
提示:
1 <= arr.length <= 3 * 10^4
1 <= arr[i] <= 3 * 10^4
该题力扣
注意是连续的子数组,不是随意取的!

首先,维护一个单调栈,每次计算栈顶的答案。即arr[i]<=arr[stk.top()]时计算,此时的此时遍历到的元素小于等于栈顶元素,而栈顶元素必然小于上一个栈内元素,故可以计算以当前栈顶元素为最小值的连续子数组的个数num,然后乘以栈顶元素。
class Solution {
public:
const int MOD=1e9+7;
int sumSubarrayMins(vector<int>& arr) {
stack<int> stk;
arr.push_back(0);//因为arr[i]>=1,最后加一个最小的元素可以保证栈中所有元素都会被弹出计算。之后stk为空,所以0不会参与计算
long ans=0;
for(int i=0;i<arr.size();++i){
while(!stk.empty()&&arr[i]<=arr[stk.top()]){//保证栈内元素是递增的
int index=stk.top();stk.pop();
int prev_index=-1;
if(!stk.empty()) prev_index=stk.top();//若栈为空上一个小元素取-1,否则取stk.top()
int prev_count=index-prev_index-1;//数量m
int next_count=i-index-1;//数量n
ans+=long(arr[index])*(prev_count+1)*(next_count+1)%MOD;
ans%=MOD;
}
stk.push(i);
}
return ans;
}
};
时间复杂度:O(n)
空间复杂度:O(n)