class Solution {
public:
//对于数组中的一个数,看他的左边有多少大于他的数,右边有多少大于它的数,两个值相乘,即以本值为最小值的连续子树组的个数,
//要找到最近的小于它的数,使用栈,递增栈,保留的是局部最小值,只用比较局部最小值即可;数组记录全局最小值;
int sumSubarr(vector<int>& nums) {
const int MOD = 1e9 + 7;
int n = nums.size();
stack<int> stk;
vector<int> left(n);
vector<int> right(n);
for(int i=0; i<=n-1; ++i){
while(!stk.empty() && nums[stk.top()] > nums[i]){ //这里把大于它的数去掉,保留了等于,防止左边扩张重复;
stk.pop();
}
if(stk.empty())left[i] = i+1;
else left[i] = i - stk.top();
stk.push(i);
}
stk = stack<int>();
for(int i=n-1; i>=0; --i){
while(!stk.empty() && nums[stk.top()] >=nums[i]){ //这里把等于它的数也去掉了,因为左边已经限制了相同数的范围,即左边是不交叉覆盖的连续子数组,右边可以交叉覆盖,结果也是不同的子数组;
stk.pop();
}
right[i] = stk.empty()? n-i : stk.top() - i;
stk.push(i);
}
long long res = 0;
for(int i=0; i<n; ++i){
res = (res + (long long)nums[i]*left[i]*right[i] ) % MOD;
}
return res;
}
};