Tìm giá trị lớn nhất của mảng sau cùng¶
Đề bài¶
Yêu cầu:
Tìm giá trị lớn nhất của mảng sau khi thực hiện loạt thao tác cộng thêm vào các phần tử.
Input:
n là số lượng các phần tử trong mảng a.
Mảng các thao tác cộng queries, mỗi phần tử gồm 3 số:
- Vị trí bắt đầu
left - Vị trí kết thúc
right - Giá trị
kmà sẽ được cộng vô các phần tử trong mảnga.
Output:
Giá trị lớn của mảng a sau khi hoàn thành các thao tác cộng của queries.
Ví dụ:
Input:
n = 10
queries:
left |
right |
k |
|---|---|---|
| 1 | 5 | 3 |
| 4 | 8 | 7 |
| 6 | 9 | 1 |
Output:
max = 10
Giải thích:
| Vị trí | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
Mảng a |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 3 | 3 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | |
| 3 | 3 | 3 | 10 | 10 | 7 | 7 | 7 | 0 | 0 | |
| 3 | 3 | 3 | 10 | 10 | 8 | 8 | 8 | 1 | 0 |
Bài giải đề xuất¶
Ý tưởng chính¶
Ứng với mỗi truy vấn, thay vì cập nhật từng phần tử trong đoạn [left..right], ta dùng mảng hiệu để ghi nhận sự thay đổi tại vị trí left và right + 1.
Sau đó, dùng một vòng lặp để cộng dồn nhằm khôi phục giá trị thực sự của các phần tử trong mảng a.
Viết chương trình¶
Bước 1:
Do mảng được đánh thứ tự từ 1, ta khởi tạo mảng a gồm n + 1 đều là 0.
Bước 2:
Duyệt từng truy vấn của mảng queries, ứng với mỗi truy vấn:
-
Vì phần tử tại vị trí
lefttăng thêmkso với phần tử đứng trước nó nên ta thực hiện:a[left] += k.Giá trị
a[left]này sẽ lan đến các vị trí tiếp theo, ta tạm thời không cộngkvào các vị trí tiếp theo đó. -
Vì phần tử tại vị trí
right + 1không được cộng thêmk, trong khi phần tử tại vị trírightđược cộng thêmkvà lan đến vị tríright + 1, nên ta thực hiệna[right + 1] -= kđể chấm dứt việc lan này.
Bước 3:
Đến lúc này, mảng a là mảng hiệu. Ta cần khôi phục các giá trị thực sự của mảng a.
Giả sử D là mảng hiệu, ta có D[i] = A[i] - A[i - 1], nghĩa là tại vị trí i, hiệu của phần tử A[i] và phần tử đứng trước nó là D[i].
Như vậy, nếu A[i] là giá trị sau cùng (sau khi hoàn thành các truy vấn trong queries) của phần tử tại vị trí i trong mảng a thì A[i] = D[i] + A[i - 1].
Nói cách khác, sau bước 2, a[i] chính là phần tử thứ i của mảng hiệu D[i], nên để tính giá trị sau cùng A[i], ta cộng dồn hiệu D[i] vô giá trị tích lũy A[i - 1] đứng trước nó.
Trong đoạn mã dưới đây, A[i] chính là giá trị của biến prefix_sum sau khi cộng dồn.
Mã nguồn¶
Code đầy đủ được đặt tại GitHub.