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