单调栈-907. 子数组的最小值之和

2022-05-25 21:40:29

问题描述:

给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。

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

 

示例 1:

输入: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。
示例 2:

输入:arr = [11,81,94,43,3]
输出:444
 

提示:

1 <= arr.length <= 3 * 104
1 <= arr[i] <= 3 * 104

问题求解:

本题需要考虑每个元素的管辖范围:对应nums[i]以其为最小值的范围[l, r]。

这一步可以通过单调栈求得。

但有一点需要特别注意:去重。

这里的去重逻辑是采用单边逻辑,例如取左边第一个小于nums[i]的位置,取右边第一个小于等于nums[i]的位置。

class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        n = len(arr)
        left = [0] * n
        right = [0] * n
        stk = []
        for i in range(n - 1, -1, -1):
            while stk and arr[stk[-1]] > arr[i]:
                stk.pop()
            right[i] = stk[-1] - i if stk else n - i
            stk.append(i)
        stk = []
        for i in range(n):
            while stk and arr[stk[-1]] >= arr[i]:
                stk.pop()
            left[i] = i - stk[-1] if stk else i + 1
            stk.append(i)
        
        res = 0
        mod = int(1e9 + 7)
        for i in range(n):
            res = (res + arr[i] * left[i] * right[i]) % mod
        return res

  

posted @ 2022-05-25 21:45  hyserendipity  阅读(32)  评论(0编辑  收藏  举报