907. 子数组的最小值之和
给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
示例一
输入: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。
暴力
class Solution {
public:
int sumSubarrayMins(vector<int>& arr) {
int res=0;
for(int i=0;i<arr.size();i++){
int temp=arr[i];
for(int j=i;j<arr.size();j++){
temp=min(temp,arr[j]);
//cout<<temp<<" ";
res=(res+temp)%1000000007;
}
cout<<endl;
}
return res;
}
};
单调栈+贡献法
class Solution {
public:
int mod=1000000007;
int sumSubarrayMins(vector<int>& arr) {
long long int res=0;
/*for(int i=0;i<arr.size();i++){
int temp=arr[i];
for(int j=i;j<arr.size();j++){
temp=min(temp,arr[j]);
//cout<<temp<<" ";
res=(res+temp)%1000000007;
}
cout<<endl;
}*/
vector<int>left(arr.size(),-1);
vector<int>right(arr.size(),arr.size());
stack<int>st;
for(int i=0;i<arr.size();i++){
while(!st.empty()&&arr[st.top()]>=arr[i])
st.pop();
if(!st.empty())
left[i]=st.top();
st.push(i);
}
while(!st.empty())
st.pop();
for(int i=arr.size()-1;i>=0;i--){
while(!st.empty()&&arr[st.top()]>arr[i])
st.pop();
if(!st.empty())
right[i]=st.top();
st.push(i);
}
for(int i=0;i<arr.size();i++){
res=(res+(long)arr[i]*(i-left[i])*(right[i]-i))%mod;
}
return res%mod;
}
};
标签:arr,907,int,st,最小值,数组,empty,size
From: https://www.cnblogs.com/SkyDusty/p/16835676.html