You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: solution/0900-0999/0907.Sum of Subarray Minimums/README_EN.md
+95
Original file line number
Diff line number
Diff line change
@@ -35,6 +35,50 @@ Sum is 17.
35
35
36
36
## Solutions
37
37
38
+
The problem asks for the sum of the minimum values of each subarray, which is actually equivalent to finding the number of subarrays for each element $arr[i]$ where $arr[i]$ is the minimum, multiplying each by $arr[i]$, and then summing these products.
39
+
40
+
Thus, the focus of the problem is translated to finding the number of subarrays for which $arr[i]$ is the minimum.
41
+
42
+
For each $arr[i]$, we identify the first position $left[i]$ to its left that is smaller than $arr[i]$ and the first position $right[i]$ to its right that is less than or equal to $arr[i]$.
43
+
44
+
The number of subarrays where $arr[i]$ is the minimum can then be given by $(i - left[i]) \times (right[i] - i)$.
45
+
46
+
It's important to note why we are looking for the first position $right[i]$ that is less than or equal to $arr[i]$ and not less than $arr[i]$.
47
+
48
+
If we were to look for the first position less than $arr[i]$, we would end up double-counting.
49
+
50
+
For instance, consider the following array:
51
+
52
+
The element at index $3$ is $2$, and the first element less than $2$ to its left is at index $0$. If we find the first element less than $2$ to its right, we would end up at index $7$. That means the subarray interval is $(0, 7)$. Note that this is an open interval.
53
+
54
+
```
55
+
0 4 3 2 5 3 2 1
56
+
* ^ *
57
+
```
58
+
59
+
If we calculate the subarray interval for the element at index $6$ using the same method, we would find that its interval is also $(0, 7)$.
60
+
61
+
```
62
+
0 4 3 2 5 3 2 1
63
+
* ^ *
64
+
```
65
+
66
+
Therefore, the subarray intervals of the elements at index $3$ and $6$ are overlapping, leading to double-counting.
67
+
68
+
If we were to find the first element less than or equal to $arr[i]$ to its right, we wouldn't have this problem.
69
+
70
+
The subarray interval for the element at index $3$ would become $(0, 6)$ and for the element at index $6$ it would be $(0, 7)$, and these two are not overlapping.
71
+
72
+
To solve this problem, we just need to traverse the array.
73
+
74
+
For each element $arr[i]$, we use a monotonic stack to find its $left[i]$ and $right[i]$.
75
+
76
+
Then the number of subarrays where $arr[i]$ is the minimum can be calculated by $(i - left[i]) \times (right[i] - i)$. Multiply this by $arr[i]$ and sum these values for all $i$ to get the final answer.
77
+
78
+
Remember to take care of data overflow and modulus operation.
79
+
80
+
The time complexity is $O(n)$, where $n$ represents the length of the array $arr$.
81
+
38
82
<!-- tabs:start -->
39
83
40
84
### **Python3**
@@ -139,6 +183,57 @@ public:
139
183
};
140
184
```
141
185
186
+
### **Rust**
187
+
188
+
```rust
189
+
const MOD: i64 = 1e9 as i64 + 7;
190
+
191
+
impl Solution {
192
+
pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 {
193
+
let n: usize = arr.len();
194
+
let mut ret: i64 = 0;
195
+
let mut left: Vec<i32> = vec![-1; n];
196
+
let mut right: Vec<i32> = vec![n as i32; n];
197
+
// Index stack, store the index of the value in the given array
198
+
let mut stack: Vec<i32> = Vec::new();
199
+
200
+
// Find the first element that's less than the current value for the left side
201
+
// The default value of which is -1
202
+
for i in 0..n {
203
+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] >= arr[i] {
204
+
stack.pop();
205
+
}
206
+
if !stack.is_empty() {
207
+
left[i] = *stack.last().unwrap();
208
+
}
209
+
stack.push(i as i32);
210
+
}
211
+
212
+
stack.clear();
213
+
214
+
// Find the first element that's less or equal than the current value for the right side
215
+
// The default value of which is n
216
+
for i in (0..n).rev() {
217
+
while !stack.is_empty() && arr[*stack.last().unwrap() as usize] > arr[i] {
218
+
stack.pop();
219
+
}
220
+
if !stack.is_empty() {
221
+
right[i] = *stack.last().unwrap();
222
+
}
223
+
stack.push(i as i32);
224
+
}
225
+
226
+
// Traverse the array, to find the sum
227
+
for i in 0..n {
228
+
ret += ((right[i] - i as i32) * (i as i32 - left[i])) as i64 * arr[i] as i64 % MOD;
0 commit comments