907. 子数组的最小值之和(贡献法,单调栈,前后缀分解)

 题目不难,但是涉及到的知识点很丰富。

细节: 左右两侧同时找小于,会重复计数,同时小于等于又会少算。

  加个限制,左侧找小于等于,右侧找小于,就可解决。

详细分析:https://leetcode.cn/problems/sum-of-subarray-minimums/solutions/2544617/javapython3cgong-xian-fa-dan-diao-zhan-z-r92z/

class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        MOD = 10 ** 9 + 7
        n = len(arr)
        pre = [-1] * n
        suf = [n] * n
        stk = []

        for i in range(n):
            while stk and arr[stk[-1]] >= arr[i]:
                stk.pop()
            if stk:
                pre[i] = stk[-1]
            stk.append(i)

        stk.clear()

        for i in range(n - 1, -1, -1):
            while stk and arr[stk[-1]] > arr[i]:
                stk.pop()
            if stk:
                suf[i] = stk[-1]
            stk.append(i)

        return sum((i - pre[i]) * (suf[i] - i) * v for i, v in enumerate(arr)) % MOD

 

posted @ 2023-11-27 17:15  深渊之巅  阅读(12)  评论(0编辑  收藏  举报