力扣907.子数组的最小值之和
-
考虑每个数对答案的贡献
- 对于每个元素 找到左边界(严格小于)
- 右边界(小于等于)
- 这样出现重复元素也不会重复计算答案
- 对于答案贡献为 arr[i] * (i - l) * (r - i)
- 对于每个元素 找到左边界(严格小于)
-
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; } };