Đăng nhập để tham gia lộ trình luyện tập
Lộ trình Prefix Sum — Tổng tiền tố từ cơ bản đến nâng cao
Giới thiệu
Prefix Sum — Tổng tiền tố là một trong những kỹ thuật nền tảng quan trọng nhất trong lập trình thi đấu.
Ý tưởng cốt lõi là:
Thay vì tính lại thông tin trên một đoạn nhiều lần, ta tính trước thông tin của các tiền tố và sử dụng hiệu giữa hai tiền tố để trả lời nhanh.
Từ một công thức rất đơn giản:
ta có thể phát triển thành nhiều kỹ thuật:
- tổng đoạn một chiều;
- đếm phần tử theo đoạn;
- XOR tiền tố;
- prefix theo modulo;
- đếm đoạn con có tổng cho trước;
- đếm đoạn con chia hết;
- tổng đoạn trên ma trận;
- tổng trên khối ba chiều;
- Difference Array;
- Imos Method;
- nhiều lớp Difference Array;
- Prefix Sum của Prefix Sum;
- Prefix Sum kết hợp Binary Search;
- Prefix Sum kết hợp Coordinate Compression;
- Prefix Sum kết hợp Fenwick Tree;
- Prefix Sum kết hợp Monotonic Queue.
Serie này được xây dựng nhằm giúp người học hiểu Prefix Sum như một mô hình tư duy, thay vì chỉ ghi nhớ một công thức.
1. Tổng tiền tố một chiều
Cho dãy:
Định nghĩa:
và:
Ta có công thức truy hồi:
với:
Khi đó tổng đoạn:
được tính bằng:
Đây là công thức nền tảng nhất của toàn bộ chuyên đề.
2. Vì sao công thức tổng đoạn đúng?
Ta có:
và:
Lấy hiệu:
thì phần:
bị triệt tiêu.
Còn lại:
Do đó:
3. Độ phức tạp
Nếu mỗi truy vấn tự cộng từ đến , một truy vấn có thể tốn:
Với truy vấn:
Sau khi xây Prefix Sum:
mỗi truy vấn chỉ còn:
Tổng:
Đây là cải tiến quan trọng khi số lượng truy vấn lớn.
4. Quy tắc dùng
Việc đặt:
giúp công thức:
đúng cả khi:
Khi đó:
Không cần xử lý riêng đoạn bắt đầu từ phần tử đầu tiên.
5. Prefix Sum trên dãy sau khi sắp xếp
Một số bài yêu cầu đồng thời:
- tổng trên dãy ban đầu;
- tổng trên dãy đã sắp xếp.
Ta xây hai mảng:
và sau khi sắp xếp:
xây:
Khi đó:
và:
Một bài toán có thể cần nhiều hệ Prefix Sum khác nhau trên cùng dữ liệu.
6. Prefix Count — Đếm bằng tổng tiền tố
Prefix Sum không nhất thiết phải cộng chính giá trị .
Ta có thể biến mỗi phần tử thành:
$$b_i= \begin{cases} 1 & \text{nếu } a_i \text{ thỏa điều kiện}\\ 0 & \text{ngược lại} \end{cases}$$Sau đó:
Khi đó:
chính là số phần tử thỏa điều kiện trong đoạn .
Đây là Prefix Count.
7. Đếm nhiều loại phần tử
Giả sử mỗi phần tử thuộc một trong loại.
Ta có thể xây:
là số phần tử thuộc loại trong:
Công thức:
Trong đó:
$$[\text{điều kiện}] = \begin{cases} 1 & \text{nếu điều kiện đúng}\\ 0 & \text{nếu điều kiện sai} \end{cases}$$Số phần tử loại trong :
8. Prefix trên quan hệ giữa hai phần tử liên tiếp
Không phải lúc nào trạng thái tại vị trí chỉ phụ thuộc vào .
Ví dụ cần đếm số vị trí:
sao cho:
Ta định nghĩa:
$$b_i= \begin{cases} 1 & \text{nếu } s_i=s_{i+1}\\ 0 & \text{ngược lại} \end{cases}$$Sau đó xây:
Với truy vấn trên đoạn ký tự , chỉ xét các cặp:
nên kết quả là:
Dạng này nhấn mạnh rằng:
Prefix Sum có thể được xây trên một dãy đặc trưng được tạo ra từ dữ liệu gốc.
9. Prefix đếm một mẫu ngắn trong chuỗi
Giả sử cần đếm số lần chuỗi "AC" xuất hiện hoàn toàn trong đoạn .
Định nghĩa:
$$b_i= \begin{cases} 1 & \text{nếu } s_i=A \text{ và } s_{i+1}=C\\ 0 & \text{ngược lại} \end{cases}$$Sau đó:
Kết quả truy vấn:
Đây là dạng tổng quát của Prefix Sum trên sự kiện cục bộ.
10. Prefix XOR
Phép XOR cũng có tính chất triệt tiêu:
và:
Ta định nghĩa:
Khi đó XOR của đoạn là:
Công thức này tương tự tổng đoạn:
nhưng phép toán được thay từ cộng sang XOR.
11. Góc nhìn đại số của Prefix Sum
Prefix Sum hoạt động tốt khi phép toán có khả năng loại bỏ phần tiền tố trước đó.
Với phép cộng:
Với XOR:
Điều quan trọng không phải chỉ là từ khóa “Sum”, mà là khả năng xây thông tin tích lũy và loại bỏ phần không cần thiết.
12. Đoạn con và hiệu hai Prefix Sum
Một đoạn con liên tiếp:
có tổng:
Do đó bài toán về đoạn con thường có thể chuyển thành bài toán về hai Prefix Sum.
Nếu cần:
thì:
hay:
Đây là phép biến đổi cực kỳ quan trọng.
13. Đếm đoạn con có tổng bằng
Ta cần đếm số cặp:
sao cho:
Tương đương:
Khi đang xét , ta cần biết trước đó có bao nhiêu Prefix Sum bằng:
Nếu:
là số Prefix Sum trước đó có giá trị , số đoạn mới kết thúc tại là:
Sau đó tăng:
14. Prefix Sum ban đầu phải được tính là một trạng thái
Ta luôn có:
Do đó ban đầu cần xem giá trị đã xuất hiện một lần:
Điều này cho phép đếm các đoạn bắt đầu từ vị trí .
Ví dụ nếu:
thì:
tương ứng đoạn:
15. Đếm đoạn con có tổng chia hết cho
Ta cần:
Tương đương:
Như vậy hai Prefix Sum có cùng phần dư sẽ tạo thành một đoạn có tổng chia hết cho .
Nếu có:
Prefix Sum mang phần dư , số cặp chọn được là:
Do đó:
$$\boxed{ \text{answer} = \sum_{r=0}^{m-1} \binom{c_r}{2} }$$với:
16. Chuẩn hóa modulo khi có số âm
Trong nhiều ngôn ngữ, nếu âm thì:
có thể nhận giá trị âm.
Để chuẩn hóa:
Khi đó:
17. Tìm đoạn dài nhất có tổng chia hết cho
Nếu:
thì đoạn:
có tổng chia hết cho .
Độ dài:
Để tối đa hóa độ dài, với mỗi phần dư , chỉ cần nhớ:
- vị trí xuất hiện đầu tiên;
- vị trí xuất hiện cuối cùng.
Nếu:
và:
là hai vị trí đó thì ứng viên:
18. Prefix Sum sau khi biến đổi dữ liệu
Nhiều bài không sử dụng trực tiếp:
mà trước tiên biến đổi .
Ví dụ với dãy chữ số:
Nếu một đoạn có độ dài bằng tổng chữ số:
chuyển vế:
Đặt:
Bài toán trở thành:
Đếm số đoạn của có tổng bằng .
Hoặc với Prefix Sum:
ta có:
suy ra:
Đặt:
Bài toán trở thành đếm các cặp Prefix Sum biến đổi bằng nhau.
Đây là một kỹ thuật rất mạnh:
Biến đổi điều kiện của đoạn thành quan hệ giữa hai trạng thái tiền tố.
19. Chia dãy thành ba phần có tổng bằng nhau
Giả sử tổng toàn dãy:
Muốn chia thành ba đoạn liên tiếp có tổng bằng nhau.
Điều kiện cần:
Đặt:
Điểm chia thứ nhất phải thỏa:
Điểm chia thứ hai phải thỏa:
với:
Khi duyệt , ta chỉ cần biết số lượng vị trí đã có:
Mỗi vị trí với:
đóng góp số điểm chia thứ nhất hợp lệ trước nó.
20. Maximum Subarray Sum bằng Prefix Sum
Tổng đoạn:
là:
Với cố định, muốn tổng lớn nhất thì cần:
nhỏ nhất.
Do đó:
$$\boxed{ \max_{1\le l\le r} (P_r-P_{l-1}) = P_r-\min_{0\le j<r}P_j }$$Duyệt từ trái sang phải và duy trì Prefix Sum nhỏ nhất đã thấy.
Đây là một cách nhìn rất quan trọng của bài toán Maximum Subarray.
21. Đoạn con có giới hạn độ dài
Giả sử cần đoạn:
với độ dài:
Đặt:
Khi đó:
suy ra:
Tổng đoạn:
Với cố định, cần tìm Prefix Sum nhỏ nhất:
trong cửa sổ chỉ số:
Do đó:
$$\boxed{ answer = \max_r \left( P_r- \min_{r-B\le i\le r-A}P_i \right) }$$Đây là nền tảng để kết hợp Prefix Sum với cấu trúc duy trì minimum động.
22. Đoạn ngắn nhất có tổng ít nhất
Ta cần:
tương đương:
Mục tiêu là tối thiểu:
Khác với trường hợp các số đều dương, khi có số âm ta không thể dùng cửa sổ trượt thông thường.
Prefix Sum giúp biến bài toán thành:
Với mỗi , tìm chỉ số càng lớn càng tốt nhưng vẫn thỏa .
Các Prefix Sum ứng viên có thể được duy trì theo thứ tự đơn điệu.
23. Đếm đoạn có tổng nhỏ hơn một giá trị
Ta cần đếm:
suy ra:
Như vậy bài toán trở thành:
Với mỗi Prefix Sum , đếm số Prefix Sum trước đó lớn hơn một ngưỡng.
Đây là cầu nối từ Prefix Sum sang:
- Coordinate Compression;
- Fenwick Tree;
- Ordered Data Structure.
24. Prefix Maximum kết hợp Prefix Sum
Trong một số bài, một truy vấn cho giới hạn và ta cần lấy tiền tố dài nhất sao cho mọi phần tử trong đó không vượt quá .
Định nghĩa:
Ta có:
Đồng thời xây:
Tìm vị trí lớn nhất sao cho:
Khi đó đáp án là:
Đây là dạng kết hợp:
$$\text{Prefix Maximum} + \text{Prefix Sum} + \text{Binary Search}$$25. Prefix Sum hai chiều
Cho ma trận:
với:
Định nghĩa:
là tổng hình chữ nhật từ:
đến:
Công thức:
$$\boxed{ P_{i,j} = a_{i,j} + P_{i-1,j} + P_{i,j-1} - P_{i-1,j-1} }$$26. Vì sao Prefix Sum 2D phải cộng rồi trừ?
Khi cộng:
vùng:
đã bị tính hai lần.
Do đó phải trừ một lần:
Đây chính là nguyên lý Inclusion-Exclusion.
27. Tổng hình chữ nhật
Xét hình chữ nhật:
Tổng là:
$$\boxed{ P_{x_2,y_2} - P_{x_1-1,y_2} - P_{x_2,y_1-1} + P_{x_1-1,y_1-1} }$$Ta:
- lấy hình chữ nhật lớn;
- trừ vùng phía trên;
- trừ vùng bên trái;
- cộng lại góc bị trừ hai lần.
28. Prefix Count 2D
Nếu ma trận chỉ cần đếm các ô thỏa điều kiện, đặt:
$$b_{i,j} = \begin{cases} 1 & \text{nếu ô }(i,j)\text{ thỏa điều kiện}\\ 0 & \text{ngược lại} \end{cases}$$Sau đó xây Prefix Sum 2D trên .
Khi đó truy vấn hình chữ nhật trả về số ô thỏa điều kiện trong:
29. Ma trận ngưỡng
Một kỹ thuật rất quan trọng là với một giá trị thử , biến ma trận thành ma trận nhị phân.
Ví dụ:
$$b_{i,j} = \begin{cases} 1 & \text{nếu } a_{i,j}>x\\ 0 & \text{ngược lại} \end{cases}$$Prefix Sum 2D cho phép nhanh chóng đếm số phần tử lớn hơn trong mọi hình vuông.
Nhờ đó ta có thể kiểm tra một điều kiện theo .
Nếu điều kiện có tính đơn điệu, có thể kết hợp với Binary Search.
Đây là dạng:
$$\boxed{ \text{Binary Search on Answer} + \text{2D Prefix Sum} }$$30. Median trong một vùng
Một vùng có:
phần tử.
Để kiểm tra một giá trị có thể là cận cho trung vị hay không, ta có thể đếm số phần tử:
hoặc:
trong từng hình vuông .
Nếu biến mỗi phần tử thành , mỗi lần kiểm tra chỉ còn là truy vấn tổng hình chữ nhật.
Đây là một ví dụ điển hình cho việc:
Prefix Sum không trực tiếp tìm đáp án, nhưng làm cho hàm kiểm tra của Binary Search trở nên đủ nhanh.
31. Prefix Sum trên các cặp đầu mút
Một đoạn có thể được biểu diễn bằng hai đầu mút:
Ta có thể xây ma trận:
biểu diễn số đối tượng có chính xác cặp đầu mút .
Sau đó xây Prefix Sum 2D.
Một truy vấn yêu cầu:
có thể chuyển thành truy vấn một miền trong mặt phẳng chỉ số.
Đây là cách biến bài toán interval thành bài toán 2D Prefix Sum.
32. Coordinate Compression kết hợp Prefix 2D
Nếu tọa độ rất lớn nhưng chỉ có điểm quan trọng, ta có thể sắp xếp các tọa độ và thay chúng bằng hạng:
Sau khi nén tọa độ, dữ liệu trở thành một lưới nhỏ hơn.
Ta có thể xây:
trên lưới đó.
Một hình chữ nhật tọa độ ban đầu trở thành truy vấn hình chữ nhật trên chỉ số đã nén.
Dạng này thường xuất hiện trong các bài:
- đếm điểm;
- đếm hình chữ nhật;
- chọn hai biên;
- kết hợp đếm số phần tử bên trong.
33. Prefix Sum ba chiều
Cho khối:
Định nghĩa:
là tổng trong khối:
Theo Inclusion-Exclusion:
$$\boxed{ \begin{aligned} P_{x,y,z} ={}&a_{x,y,z} +P_{x-1,y,z} +P_{x,y-1,z} +P_{x,y,z-1}\\ &-P_{x-1,y-1,z} -P_{x-1,y,z-1} -P_{x,y-1,z-1}\\ &+P_{x-1,y-1,z-1} \end{aligned} }$$34. Tổng một hình hộp
Cần tính tổng trong:
Đặt:
Kết quả:
$$\begin{aligned} S={}& F(x_2,y_2,z_2)\\ &-F(x_1-1,y_2,z_2) -F(x_2,y_1-1,z_2) -F(x_2,y_2,z_1-1)\\ &+F(x_1-1,y_1-1,z_2) +F(x_1-1,y_2,z_1-1) +F(x_2,y_1-1,z_1-1)\\ &-F(x_1-1,y_1-1,z_1-1) \end{aligned}$$Đây là Inclusion-Exclusion trong ba chiều.
35. Quy luật Inclusion-Exclusion nhiều chiều
Trong một chiều:
Trong hai chiều:
Trong ba chiều:
Dấu phụ thuộc vào số chiều bị dịch về biên trước.
Có thể hiểu bằng công thức:
với là số tọa độ dùng biên trái trừ .
36. Difference Array — Mảng hiệu
Prefix Sum thường dùng cho:
nhiều truy vấn đọc trên dữ liệu tĩnh.
Difference Array thường dùng cho:
nhiều cập nhật đoạn rồi mới cần dữ liệu cuối cùng.
Cho dãy:
Định nghĩa:
và:
với:
Ta có thể khôi phục:
hay:
Như vậy:
Prefix Sum và Difference Array là hai phép biến đổi ngược nhau.
37. Cộng cho cả đoạn
Muốn:
với:
ta chỉ cần:
và nếu tồn tại :
Sau tất cả cập nhật, lấy Prefix Sum của để thu được giá trị thật.
Mỗi cập nhật chỉ mất:
38. Vì sao phải trừ tại ?
Khi cộng:
Prefix Sum từ trở đi đều tăng .
Nhưng ta chỉ muốn ảnh hưởng đến:
Do đó tại vị trí:
phải hủy hiệu ứng bằng:
Kết quả:
- trước : không đổi;
- từ đến : tăng ;
- sau : hiệu ứng bị triệt tiêu.
39. Difference Array để đếm số lần một vị trí được phủ
Mỗi đoạn:
đóng góp:
cho mọi vị trí trong đoạn.
Ta cập nhật:
Sau khi Prefix Sum:
thì:
là số đoạn phủ vị trí .
40. Tối ưu tổng bằng số lần xuất hiện
Giả sử vị trí được sử dụng:
lần.
Tổng đóng góp:
Nếu có quyền hoán vị các giá trị , để tối đa tổng ta sắp:
và:
rồi ghép cùng thứ tự:
Đây là sự kết hợp:
41. Hai lớp Difference Array
Có những bài có:
- phần tử;
- phép cập nhật;
- truy vấn, mỗi truy vấn yêu cầu thực hiện một đoạn các phép cập nhật.
Giả sử phép cập nhật thứ tác động lên:
với giá trị:
Trước tiên cần tính số lần mỗi phép cập nhật được thực hiện.
Dùng Difference Array trên chỉ số phép toán:
Sau Prefix Sum:
là số lần phép cập nhật thứ được thực hiện.
Khi đó phép thứ thực sự cộng:
vào đoạn:
Tiếp tục dùng Difference Array thứ hai trên dãy ban đầu.
Đây là:
$$\boxed{\text{Difference of operations}+\text{Difference of array}}$$42. Difference Array hai chiều
Muốn cộng cho toàn bộ hình chữ nhật:
ta cập nhật bốn góc:
Sau tất cả cập nhật, lấy Prefix Sum hai chiều:
$$A_{i,j} = D_{i,j} + A_{i-1,j} + A_{i,j-1} - A_{i-1,j-1}$$Khi đó là tổng tác động tại ô .
43. Imos Method hai chiều
2D Difference Array thường được gọi là 2D Imos Method.
Ứng dụng:
- phủ nhiều hình chữ nhật;
- tô nhiều vùng;
- đếm số lớp phủ tại mỗi ô;
- tính diện tích được phủ đúng lần;
- tính diện tích được phủ ít nhất một lần.
Nếu:
là số hình chữ nhật phủ ô , ta có thể đếm:
hoặc:
44. Prefix Sum của Prefix Sum
Cho:
Tiếp tục định nghĩa:
Ta gọi là Prefix Sum cấp hai.
Khai triển:
Mỗi xuất hiện trong:
tổng cộng:
lần.
Do đó:
Prefix cấp hai thường xuất hiện khi cần tổng của nhiều tổng đoạn.
45. Tổng tất cả Prefix Sum trên một đoạn
Ta có:
Khi đó:
bằng:
Ý tưởng này có thể tiếp tục lên Prefix cấp ba nếu cấu trúc bài yêu cầu.
46. Tổng của các đoạn có cùng điểm đầu
Với điểm đầu cố định:
Tổng các đoạn:
là:
Suy ra:
Dùng Prefix cấp hai:
nên:
$$\boxed{ \sum_{j=l}^{r}S(l,j) = Q_r-Q_{l-1} - (r-l+1)P_{l-1} }$$Đây là một công thức quan trọng trong các bài tổng của nhiều subarray sum.
47. Tổng mọi đoạn con của một dãy
Mỗi phần tử xuất hiện trong bao nhiêu đoạn con?
Điểm đầu có thể chọn:
nên có:
cách.
Điểm cuối có thể chọn:
nên có:
cách.
Do đó xuất hiện trong:
đoạn.
Tổng tất cả tổng đoạn con là:
Đây là một cách nhìn đóng góp thay cho việc liệt kê mọi đoạn.
48. Flatten các tổng đoạn con
Một số bài sắp các tổng đoạn theo thứ tự:
Nhóm bắt đầu tại có:
phần tử.
Số phần tử trước nhóm là:
Khai triển:
Do đó vị trí bắt đầu của nhóm trong dãy phẳng có thể được xác định bằng công thức Prefix theo số lượng.
Sau khi xác định nhóm chứa một vị trí, tổng một phần nhóm có thể được tính bằng Prefix cấp hai.
Đây là dạng Prefix Sum nâng cao:
$$\boxed{ \text{Prefix trên số lượng} + \text{Prefix trên giá trị} + \text{Prefix cấp hai} }$$49. Prefix Sum và Binary Search
Nếu có hàm Prefix đơn điệu:
ta có thể tìm vị trí đầu tiên hoặc cuối cùng thỏa điều kiện bằng Binary Search.
Ví dụ tìm lớn nhất sao cho:
hoặc nhỏ nhất sao cho:
Lưu ý:
Prefix Sum chỉ đơn điệu nếu dữ liệu cộng vào không âm.
Nếu có số âm:
không nhất thiết tăng.
50. Prefix Sum và Two Pointers
Nếu:
thì khi mở rộng đầu phải , tổng cửa sổ không giảm.
Điều này cho phép dùng Two Pointers cho các điều kiện như:
hoặc:
Prefix Sum vẫn giúp hiểu bản chất:
nhưng tính đơn điệu của dữ liệu dương cho phép xử lý nhanh hơn bằng hai con trỏ.
Nếu có số âm, tính đơn điệu này biến mất.
51. Prefix Sum và Coordinate Compression
Các Prefix Sum:
có thể rất lớn hoặc âm.
Nếu cần đưa chúng vào Fenwick Tree hoặc một cấu trúc dựa trên chỉ số, ta có thể:
- thu thập tất cả giá trị Prefix Sum;
- sắp xếp;
- loại bỏ giá trị trùng;
- thay mỗi giá trị bằng thứ hạng.
Nếu:
thì ánh xạ:
Bản chất thứ tự vẫn được bảo toàn.
52. Prefix Sum và Fenwick Tree
Prefix Sum tĩnh trả lời:
rất nhanh nhưng khó xử lý cập nhật.
Fenwick Tree mở rộng ý tưởng Prefix Sum sang dữ liệu động.
Hai thao tác cơ bản:
- cập nhật một vị trí;
- lấy tổng tiền tố.
Nếu:
thì tổng đoạn vẫn là:
Điểm khác biệt là dữ liệu có thể thay đổi giữa các truy vấn.
53. Static Prefix Sum và Dynamic Prefix Sum
Nếu dữ liệu không thay đổi:
thường là lựa chọn đơn giản nhất.
Xây dựng:
Truy vấn:
Nếu có cập nhật điểm:
thường phù hợp hơn.
Cập nhật:
Truy vấn:
Đây là bước phát triển tự nhiên từ Static Range Sum sang Dynamic Range Sum.
54. Sai lầm thường gặp — lệch chỉ số
Công thức chuẩn:
và:
Sai phổ biến:
Công thức này làm mất phần tử .
55. Sai lầm thường gặp — quên
Nếu không có:
các đoạn bắt đầu tại:
phải xử lý riêng.
Nên luôn tạo trạng thái Prefix rỗng:
56. Sai lầm thường gặp — overflow
Nếu:
và:
thì tổng có thể đạt khoảng:
vượt giới hạn số nguyên 32-bit.
Trong C++ nên dùng:
cho:
- Prefix Sum;
- đáp án;
- tích số;
- số lượng cặp lớn.
57. Sai lầm thường gặp — dùng Prefix Sum khi dữ liệu thay đổi
Prefix Sum tĩnh giả sử:
không thay đổi sau khi xây mảng.
Nếu một phần tử thay đổi, tất cả:
phía sau vị trí đó đều thay đổi.
Do đó nếu có nhiều cập nhật xen kẽ truy vấn, cần chuyển sang cấu trúc động.
58. Sai lầm thường gặp — modulo âm
Không nên chỉ dùng:
nếu có thể âm.
Nên chuẩn hóa:
59. Sai lầm thường gặp — nhầm Prefix Sum và Sliding Window
Prefix Sum:
- dùng được với số âm;
- cho phép truy vấn đoạn bất kỳ;
- không yêu cầu cửa sổ đơn điệu.
Sliding Window thường cần một tính đơn điệu nhất định.
Ví dụ với dãy số dương, tổng cửa sổ tăng khi mở rộng sang phải.
Nhưng khi có số âm, tính chất này không còn đúng.
60. Sai lầm thường gặp — Prefix Sum 2D thiếu góc cộng lại
Công thức đúng:
$$P_{i,j} = a_{i,j} + P_{i-1,j} + P_{i,j-1} - P_{i-1,j-1}$$Và truy vấn:
$$P_{x_2,y_2} - P_{x_1-1,y_2} - P_{x_2,y_1-1} + P_{x_1-1,y_1-1}$$Dấu cộng cuối cùng là bắt buộc vì vùng giao đã bị trừ hai lần.
61. Sai lầm thường gặp — Difference Array quên điểm kết thúc
Cập nhật đoạn:
phải gồm:
và:
nếu còn trong miền chỉ số.
Nếu chỉ cộng ở , tác động sẽ kéo dài đến cuối mảng.
62. Mô hình tư duy tổng quát
Khi gặp bài toán đoạn, hãy thử đặt:
Sau đó hỏi:
Thông tin của có thể được suy ra từ hai tiền tố và hay không?
Nếu có, Prefix Sum có thể là hướng phù hợp.
63. Mô hình biến đổi đoạn con
Nếu đề cho điều kiện:
hãy thử viết lại bằng Prefix:
Sau đó chuyển điều kiện thành:
hoặc:
hoặc:
Từ đây bài toán có thể trở thành:
- đếm giá trị bằng nhau;
- đếm giá trị nhỏ hơn;
- tìm minimum;
- tìm maximum;
- tìm phần dư giống nhau.
64. Các mô hình công thức cần ghi nhớ
Tổng đoạn
XOR đoạn
$$\boxed{ \operatorname{xor}(l,r)=X_r\oplus X_{l-1} }$$Đoạn có tổng bằng
hay:
Đoạn có tổng chia hết cho
Maximum Subarray
Prefix Sum 2D
$$\boxed{ P_{i,j} = a_{i,j} + P_{i-1,j} + P_{i,j-1} - P_{i-1,j-1} }$$Rectangle Sum
$$\boxed{ P_{x_2,y_2} - P_{x_1-1,y_2} - P_{x_2,y_1-1} + P_{x_1-1,y_1-1} }$$Difference Array update
$$\boxed{ D_l\mathrel{+}=x,\qquad D_{r+1}\mathrel{-}=x }$$Khôi phục Difference Array
Tổng mọi subarray
65. Các tầng kiến thức trong serie
Serie được sắp xếp theo hướng tăng dần độ khó.
Tầng 1 — Prefix Sum trực tiếp
Mục tiêu:
- hiểu ;
- truy vấn tổng đoạn;
- làm quen ;
- tránh lỗi chỉ số.
Công thức chính:
Tầng 2 — Prefix Count và Prefix XOR
Mục tiêu:
- hiểu rằng Prefix không chỉ dùng cho phép cộng;
- xây dãy đặc trưng;
- đếm điều kiện trên đoạn;
- XOR đoạn.
Tầng 3 — Prefix Sum và đoạn con
Mục tiêu:
- chuyển đoạn con thành hiệu hai Prefix Sum;
- đếm tổng bằng ;
- đếm tổng chia hết;
- biến đổi điều kiện về Prefix bằng nhau.
Tầng 4 — Prefix Sum và tối ưu
Mục tiêu:
- maximum subarray;
- đoạn có giới hạn độ dài;
- đoạn ngắn nhất đạt ngưỡng;
- Prefix Maximum;
- Binary Search;
- cấu trúc đơn điệu.
Tầng 5 — Prefix nhiều chiều
Mục tiêu:
- 2D Prefix Sum;
- Inclusion-Exclusion;
- Rectangle Query;
- Threshold Matrix;
- Coordinate Compression;
- 3D Prefix Sum.
Tầng 6 — Difference Array
Mục tiêu:
- Range Update;
- phủ đoạn;
- nhiều lớp cập nhật;
- 2D Difference;
- Imos Method.
Tầng 7 — Prefix nâng cao
Mục tiêu:
- Prefix cấp hai;
- tổng của nhiều subarray;
- Flatten subarray sums;
- Prefix kết hợp Fenwick Tree;
- chuyển từ Static Query sang Dynamic Query.
67. Mục tiêu sau khi hoàn thành serie
Sau khi hoàn thành toàn bộ serie, người học cần có khả năng nhận ra các biểu hiện sau:
- “nhiều truy vấn tổng đoạn” Prefix Sum;
- “đếm điều kiện trên đoạn” Prefix Count;
- “XOR đoạn” Prefix XOR;
- “đếm đoạn có tổng ” hai Prefix Sum;
- “chia hết cho ” phần dư Prefix Sum;
- “maximum subarray” Prefix Sum nhỏ nhất phía trước;
- “nhiều Rectangle Query” 2D Prefix Sum;
- “nhiều Cuboid Query” 3D Prefix Sum;
- “nhiều cập nhật đoạn” Difference Array;
- “nhiều cập nhật hình chữ nhật” 2D Difference;
- “truy vấn trên các phép cập nhật” Difference nhiều tầng;
- “tổng của nhiều tổng đoạn” Prefix của Prefix;
- “cập nhật động” Fenwick Tree hoặc Segment Tree.
Quan trọng hơn, cần hình thành phản xạ:
Khi thấy một đoạn liên tiếp, hãy thử biểu diễn nó bằng hiệu của hai tiền tố.
68. Công thức tổng kết
Một chiều:
Hai chiều:
$$\boxed{ P_{i,j} = a_{i,j} + P_{i-1,j} + P_{i,j-1} - P_{i-1,j-1} }$$Ba chiều:
$$\boxed{ \begin{aligned} P_{x,y,z} ={}&a_{x,y,z} +P_{x-1,y,z} +P_{x,y-1,z} +P_{x,y,z-1}\\ &-P_{x-1,y-1,z} -P_{x-1,y,z-1} -P_{x,y-1,z-1}\\ &+P_{x-1,y-1,z-1} \end{aligned} }$$Difference Array:
Đếm đoạn tổng :
Đếm đoạn chia hết cho :
Maximum Subarray:
$$\boxed{ \max_r \left( P_r-\min_{0\le i<r}P_i \right) }$$Prefix cấp hai:
Tổng mọi đoạn con:
Đây là hệ công thức cốt lõi của toàn bộ chuyên đề Prefix Sum.
- Người tham gia
- 3
- Tạo bởi