力扣OJ 907. 子數組的最小值之和(單調棧)

給定一個整數數組 A,找到 min(B) 的總和,其中 B 的範圍爲 A 的每個(連續)子數組。

由於答案可能很大,因此返回答案模 10^9 + 7。

 

示例:

輸入:[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。
 

提示:

1 <= A <= 30000
1 <= A[i] <= 30000

 

 

//翻轉vector
template<typename T>
vector<T> frev(vector<T> v)
{
    vector<T> ans;
    for(int i=v.size()-1;i>=0;i--)ans.push_back(v[i]);
    return ans;
}
//vector乘一個數
template<typename T>
void fcheng(vector<T> &v,int n)
{
    for(int i=v.size()-1;i>=0;i--)v[i]*=n;
}
//vector加一個數
template<typename T>
void fjia(vector<T> &v,int n)
{
    for(int i=v.size()-1;i>=0;i--)v[i]+=n;
}
//返回vector每個數前面最近的比它小的數的ID,-1 或者 0到size-1
template<typename T>
vector<int> fminlef(vector<T> v)
{
    vector<int> ans;
    if(v.size()==0)return ans;
    stack<T>st;
    st.push(0);
    ans.push_back(-1);
    for(int i=1;i<v.size();i++)
    {
        while(!st.empty() && v[st.top()]>=v[i])st.pop();
        if(st.empty())ans.push_back(-1);
        else ans.push_back(st.top());
        st.push(i);
    }
    return ans;
}
//返回vector每個數後面最近的比它小的數的ID,size 或者 0到size-1
template<typename T>
vector<int> fminrig(vector<T> v)
{
    vector<int>v1=frev(v),v2=fminlef(v1);
    fcheng(v2,-1);
    fjia(v2,v.size()-1);
    return frev(v2);
}
//返回vector每個數前面最近的比它小或等於的數的ID,-1 或者 0到size-1
template<typename T>
vector<int> fminlef2(vector<T> v)
{
    vector<int> ans;
    if(v.size()==0)return ans;
    stack<T>st;
    st.push(0);
    ans.push_back(-1);
    for(int i=1;i<v.size();i++)
    {
        while(!st.empty() && v[st.top()]>v[i])st.pop();
        if(st.empty())ans.push_back(-1);
        else ans.push_back(st.top());
        st.push(i);
    }
    return ans;
}
//返回vector每個數後面最近的比它小或等於的數的ID,size 或者 0到size-1
template<typename T>
vector<int> fminrig2(vector<T> v)
{
    vector<int>v1=frev(v),v2=fminlef2(v1);
    fcheng(v2,-1);
    fjia(v2,v.size()-1);
    return frev(v2);
}

class Solution {
public:
    int sumSubarrayMins(vector<int>& A) {
        vector<int>v1=fminlef(A),v2=fminrig2(A);
        int ans=0;
        for(int i=0;i<A.size();i++)
        {
            int m=min(i-v1[i],v2[i]-i);
            ans+=(v2[i]-v1[i]-m)*m*A[i],ans%=1000000007;
        }
        return ans;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章