首页 > 其他分享 >LC 907 Sum of Subarray Minimums

LC 907 Sum of Subarray Minimums

时间:2022-10-26 22:33:05浏览次数:48  
标签:arr right Minimums int Sum stk 数组 Subarray left

Decrisption

Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Since the answer may be large, return the answer modulo \(10^9\) + 7.

Input

Example 1:

Input: \(arr = [3,1,2,4]\)
Output: 17
Explanation:
Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].
Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1.
Sum is 17.
Example 2:

Input: \(arr = [11,81,94,43,3]\)
Output: 444

Constraints

1\(\leq\)arr.length$\leq$3\(10^4\)
1\(\leq\)arr[i]$\leq$3
\(10^4\)

Solution

思路:
方法一:暴力计算
直接计算每一个子数组中的最小值并全部相加,时间复杂度为\(O\)(\(n^2\)),显然会超时。

class Solution {
public:
    int MOD=1e9+7;
    int sumSubarrayMins(vector<int>& arr) {
        int n=arr.size();
        int ans=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<=i;j++){
                int min=*min_element(arr.begin()+j,arr.begin()+i+1);
                ans+=min;
                ans%=MOD;
            }
        }
        return ans;
    }
};

方法二:两次单调栈+贡献法
方法一中由于重复计算了许多次相同的最小值,所以我们要想办法免去复杂计算。对于数组中的每一个元素,其都会在最终的答案中有一个贡献值。该贡献值可以看成是每一个元素作为子数组的最小元素的次数。

注意到:对于某一个元素\(x\),假定其下标为\(i\),如果x是某一个子数组的最小值,该子数组的左端点为\(left\),右端点为\(right\),那么在[\(left\),\(right\)]范围内所有包含\(x\)的子数组的最小值都为x,x的贡献为\(arr[i]\)\(*\)(\(i-left\))\(*\)(\(right-i\))。所以我们要找到每一个元素左侧第一个小于该元素的位置\(left\)和右侧第一个小于该元素的位置\(right\)。这样在区间\((left,right)\)范围内包含\(x\)的子数组的最小值可以确定为x,x的贡献值为\(arr[i]*(i-left)*(right-i)\).

class Solution {
public:
    int MOD=1e9+7;
    typedef long long ll;
    int sumSubarrayMins(vector<int>& arr) {
        int n=arr.size();
        ll ans=0;
        vector<ll> left(n,-1);    //左边界为-1
        vector<ll> right(n,n);   //右边界为n
        stack<ll> stk;
        for(int i=0;i<n;i++){
            while(!stk.empty()&&arr[stk.top()]>arr[i]){
                stk.pop();
            }
            if(!stk.empty()){
                left[i]=stk.top();
            }
            stk.push(i);
        }

        while(!stk.empty()) stk.pop();

        for(int i=n-1;i>=0;i--){
            while(!stk.empty()&&arr[stk.top()]>=arr[i]){
                stk.pop();
            }
            if(!stk.empty()){
                right[i]=stk.top();
            }
            stk.push(i);
        }

        for(ll i=0;i<n;i++){
            ans+= (ll)arr[i]*(i-left[i])*(right[i]-i);
            ans%=MOD;
        }
        return ans;
    }
};

时间复杂度:\(O(n)\)
空间复杂度:\(O(n)\)

标签:arr,right,Minimums,int,Sum,stk,数组,Subarray,left
From: https://www.cnblogs.com/yjx-7355608/p/16830355.html

相关文章

  • Leetcode第862题:和至少为K的最短子数组(Shortest Subarray with sum at least k)
    解题思路前缀和定义前缀和\(s[0]=0\),\(s[i+1]=\displaystyle\sum\limits_{j=0}^inums[j]\)。例如\(nums=[1,2,-1,2]\),对应的前缀和数组为\(s=[0,1,3,2,4]\)。......
  • Luogu P4868 Preprefix sum
    题目链接:​​传送门​​线段树维护前缀和简单明了修改就修改当然还有更快的树状数组差分的做法*/#include<iostream>#include<cstdio>#include<cstring>#include<cs......
  • Kafka Server之kafka-console-consumer.bat
    KafkaServer之kafka-console-consumer.bat注意:博主使用kafka版本:kafka_2.12-3.3.1.tgzwindows版一、订阅主题全部消息(注意:Producer已经生产:0~4999共5000条消息)在k......
  • E. Permutation by Sum
    传送门题意:给出n,l,r,s,要求构造一个序列,要求满足l,r区间的和是s,存在就是输出序列,否则就-1思路:首先判断是否-1,很简单,就是一个区间里面的最大值和最小值,s必须......
  • Sum of Matchings (图论,求所有区间贡献问题,)
    题意: 思路:是图论,看给出的信息能不能构成一些特殊的图本题就是不相交的环,每次拆分可以变成不相交的环+链环的匹配就是点数/2,链也是点数/2(向下取整) ......
  • HDU 3349 Consumer
    ​​题目链接​​题目背景有依赖的背包,下面用我常用的变量和说法。题目大意有个主件和块钱,每个主件都有费用和对应的个附件,附件也有费用与价值,购买主件后才能购买附件,问怎......
  • LOJ #6220. sum
    题目链接:​​传送门​​官方题解:有一个结论:必有连续的一串数和为n的倍数证明:先求个前缀和若这个前缀和中有的倍数,则这个前缀即为答案若这个前缀和中没有的倍数,即模余~......
  • C2. Make Nonzero Sum (hard version)
    C2.MakeNonzeroSum(hardversion)timelimitpertest2secondsmemorylimitpertest256megabytesinputstandardinputoutputstandardoutputThisi......
  • C1. Make Nonzero Sum (easy version)
    C1.MakeNonzeroSum(easyversion)Thisistheeasyversionoftheproblem.Thedifferenceisthatinthisversionthearraycannotcontainzeros.Youcanma......
  • 4.5 Kafka Consumer API之多线程并发处理
    1.Consumer一对一消费Partition(1).简介这种类型是经典模式,每一个线程单独创建一个KafkaConsumer消费一个partition,用于保证线程安全。(2).代码示例publicclassKafkaCon......