907. 子数组的最小值之和
给定一个整数数组 arr
,找到 min(b)
的总和,其中 b
的范围为 arr
的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7
。
思路同乘法原理 LeetCode 828. 统计子串中的唯一字符-CSDN博客
遍历arr[i]时,找左边第一个比arr[i]的下标L,找右边第一个比arr[i]小的下标R。
那么区间左端点取 L+1,i
区间右端点取i,R-1。
注意如果出现重复元素,这样找会重复计算。
如[1,2,3,4,2] 子数组2,3,4,2在遍历时会加两次2,所以防止重复计算,左边不能取等或右边不能取等。
使用单调栈来找左边第一个比当前数小的下标(数)。
【单调栈】单调栈模板_单调栈 模板_暮色_年华的博客-CSDN博客
使用left[i]表示小于arr[i] 左边的第一个下标
使用right[i]表示小于等于arr[i]右边的第一个下标
class Solution {
public:int sumSubarrayMins(vector<int>& arr) {const int MOD=1e9+7;//使用单调栈//left[i]表示arr[i]左边第一个比arr[i]小的下标//right[i]表示arr[i]右边第一个比arr[i]小的下标stack<int>st;int n=arr.size();vector<int>left(n,-1);vector<int>right(n,n);for(int i=0;i<n;i++){while(!st.empty()&&arr[st.top()]>=arr[i])st.pop();if(st.empty())left[i]=-1;else left[i]=st.top();st.push(i);}while(!st.empty())st.pop();for(int i=n-1;i>=0;i--){while(!st.empty()&&arr[st.top()]>arr[i])st.pop();if(st.empty())right[i]=n;else right[i]=st.top();st.push(i);}long res=0L;for(int i=0;i<n;i++){res+=(long)(i-left[i])*(right[i]-i)*arr[i];}return res%MOD;}};
注意取模
long res=0;
res+=(long) ;
res%MOD;