单调栈-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