力扣907.子数组的最小值之和
-
考虑每个数对答案的贡献
- 对于每个元素 找到左边界(严格小于)
- 右边界(小于等于)
- 这样出现重复元素也不会重复计算答案
- 对于答案贡献为 arr[i] * (i - l) * (r - i)
- 对于每个元素 找到左边界(严格小于)
cpp
class Solution {
const int MOD = 1e9+7;
public:
int sumSubarrayMins(vector<int>& arr) {
int n = arr.size();
vector<int> l(n,-1),r(n,n);
stack<int> st;
for(int i=0;i<n;i++)
{
while(!st.empty() && arr[st.top()] >= arr[i]) st.pop();
if(!st.empty()) l[i] = st.top();
st.push(i);
}
st = stack<int>();
for(int i=n-1;i>=0;i--)
{
while(!st.empty() && arr[st.top()] > arr[i]) st.pop();
if(!st.empty()) r[i] = st.top();
st.push(i);
}
long res=0L;
for(int i=0;i<n;i++)
{
res += (long)arr[i] * (i - l[i]) * (r[i] - i);
}
return res % MOD;
}
};