---
# System prepended metadata

title: 907. Sum of Subarray Minimums

---

Daily 20/01/2024: [907. Sum of Subarray Minimums](https://leetcode.com/problems/k-inverse-pairs-array/)

# 1. Tóm tắt đề bài
Cho một mảng các số nguyên ```arr```, hãy tìm tổng của ```min(b)```, trong đó b là các mảng con (liên tiếp) của ```arr```.
Trả về kết quả theo modulo $10^9 + 7$.

#### Giới hạn
- $1 \le$ ```arr.length``` $\le 3 \cdot 10^4$
- $1 \le$ ```arr[i]``` $\le 3 \cdot 10^4$

# 2. Tóm tắt lời giải

#### Phân tích
- Trước hết nếu mà chúng ta làm theo phương pháp chạy trâu, độ phức tạp có thể lên tới $O(n^3)$ hoặc cải tiến hơn bằng các cấu trúc dữ liệu khác như Segment Tree hay RMQ thì cũng sẽ không cải thiện lắm.
- Vì vậy cần nghĩ ra hướng giải khác, nhận xét rằng 1 vị trí ở mảng có thể làm min của rất nhiều mảng con, vì vậy chúng ta cần khai thác ở điểm này. Nó sẽ hướng chúng ta đến một bài toán quy hoạch động cơ bản. Lưu ý là các mảng con là các dãy liên tiếp.
- Thật vậy nếu ta xét ```dp[i]``` là tổng của tất cả các mảng con liên tiếp có chứa ```arr[i]```. Sẽ có 2 trường hợp xảy ra:
    - ```arr[i]``` nhỏ nhất trong ```arr[0...i]``` khi đó ```dp[i]``` đơn giản là ```(i + 1) * arr[i]``` vì có ```i + 1``` mảng con chứa ```i```.
    - Tồn tại ```k``` mà ```arr[i]``` nhỏ nhất trong ```arr[k..i]```  như vậy với các mảng con từ ```arr[0..i]``` cho tới ```arr[k..i]``` thì sẽ có tổng các min là bài toán con ```dp[k]``` và từ ```arr[k + 1: ...i]``` tới ```arr[i..i]``` có tổng các min là ```arr[i] * (i - k)``` vì ```arr[i]``` nhỏ nhất khi xét các mảng con đấy.
 
- Kết quả của bài toán sẽ tổng của tất cả các ```dp[i]```.
# 3. Lời giải chi tiết
- Xây dựng 1 stack để tìm được phần tử k mà ```arr[i]``` nhỏ nhất trong ```arr[k..i]```

#### Code
```python
class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        stack = []
        result = 0
        mod = 10 ** 9 + 7
        dp = [0] * len(arr)


        for i in range(len(arr)):
            while stack and arr[i] <= arr[stack[-1]]:
                stack.pop()
            
            if stack:
                j = stack[-1]
                dp[i] = dp[j] + arr[i] * (i - j)
            else:
                dp[i] =  arr[i] * (i + 1)

            result += dp[i]
            result %= mod
            stack.append(i)
        
        return result


```
#### Độ phức tạp
$O(n)$
# 4. Kết luận & gợi ý mở rộng
- Bài này khá hay về tính vận dụng 
> Hãy dùng nghị lực và sự kiên trì để đánh bại mọi thứ.

###### #Hashtag: <span style='color: blue'>Hash Map</span>