907. 子数组的最小值之和

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;
    }
};

单调栈+贡献法

OX3F题解

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;
    }
};
posted @ 2022-10-28 12:06  认真游泳的鱼  阅读(20)  评论(0)    收藏  举报