具体思路:
dp超时,整体思路为左右拓展思路;
如果枚举每个值,向两个方向搜索,则必定会得到一个区间,使得该区间内以该值中心元素最小;
所以只需要按照该思路进行枚举即可,但是可惜会超时;
所以采用单调栈;
维护一个递增栈,栈内存放索引,当一个元素小于栈顶元素,则进行弹栈;
但是这里很多题解都没说明白,弹栈并不是计算该元素的左右区间,而是计算栈内节点的左右区间;
例如:3,4,5,1序列;
如果遍历到元素1,则说明3,4,5的右边界都为1;
此时,比较难的是左边的确定,即为什么左边界就是自己的栈内的下一个元素;
因为是单调递增栈,所以栈内每个元素都比下一位元素要大,因此,左边界可以确定;
并且每次算完之后,都会把计算后的元素弹栈,为新入栈的元素做好左边界准备;
例如:0,3,4,5,1;
1入栈后,栈内坐标必定为0,4;
当出现比1小的元素,会对1进行判断,所以左边界直接就是4-0=left;
具体代码:
using ll=long long;
class Solution {
public:
int sumSubarrayMins(vector<int>& arr) {
stack<int>st;
ll mod=pow(10,9)+7;
ll ret=0;
arr.push_back(-1);
for(int i=0;i<arr.size();i++){
while(!st.empty()&&arr[st.top()]>=arr[i]){
int index=st.top();
st.pop();
int right=i-index;
int l=st.empty()?-1:st.top();
int left=index-l;
ll temp=left*right*ll(arr[index])%mod;
ret+=temp%mod;
ret%=mod;
}
st.push(i);
}
return ret;
}
};