import java.util.Deque;
import java.util.LinkedList;/** 参考链接:https://leetcode.cn/problems/sum-of-subarray-minimums/solutions/1930857/gong-xian-fa-dan-diao-zhan-san-chong-shi-gxa5/* https://leetcode.cn/problems/sum-of-subarray-minimums/solutions/1931139/-by-muse-77-367z/* 单调栈* 思路:将求取每个连续的子数组的最小值之和,转换为求:以每个数为最小值然后求以该数* 为最小值子数组的个数,然后个数乘以该最小值得到的数加到结果集中。重复这样的* 操作遍历全部的数。** 问题:如何找到以该数为最小值的数组个数。* 想要解决这个问题,需要明白 乘法原理: 最小值左边的数乘以右边的数等于该数全部的连续子序列的个数** 栈中存储的全部是下标,但数值是从栈底到栈顶是单调递增的。*** @auther start* @create 2023-11-26 21:35*/
public class L907 {private static final long MOD = (long) 1e9 + 7;public int sumSubarrayMins(int[] arr) {long ans = 0;Deque<Integer> st = new LinkedList<>();st.push(-1);for (int r = 0; r <= arr.length; r++) {int x = r < arr.length ? arr[r] : -1;// x 小于栈顶元素,栈顶元素出栈,新的栈顶元素是该元素的// 左边界,r是该元素的有边界。while (st.size() > 1 && arr[st.peek()] >= x) {int i = st.pop();//将该最小值组成的元素个数乘以该最小值的结果添加到结果集中。ans += (long) arr[i] * (i - st.peek()) * (r - i);}st.push(r);}//输出结果return (int) (ans % MOD);}
}