Giả sử bạn có một mảng trống:
0 0 0 0 0 0 0 0 0 0 (array)
0 0 0 0 0 0 0 0 0 0 (cumulative sums)
Và bạn muốn thực hiện cập nhật phạm vi từ +5 đến [3..7]:
0 0 0 5 5 5 5 5 0 0 (array)
0 0 0 5 10 15 20 25 25 25 (desired cumulative sums)
Làm thế nào bạn có thể lưu trữ các khoản tiền tích lũy mong muốn bằng cách sử dụng 2 cây được lập chỉ mục nhị phân?
Bí quyết là sử dụng hai cây được lập chỉ mục nhị phân là BIT1 và BIT2, trong đó tổng tích lũy được tính từ nội dung của chúng. Trong ví dụ này, đây là những gì chúng tôi sẽ lưu trữ trong hai cây:
0 0 0 5 5 5 5 5 0 0 (BIT1)
0 0 0 10 10 10 10 10 -25 -25 (BIT2)
Để tìm sum[i]
, bạn tính toán này:
sum[i] = BIT1[i] * i - BIT2[i]
Ví dụ:
sum[2] = 0*2 - 0 = 0
sum[3] = 5*3 - 10 = 5
sum[4] = 5*4 - 10 = 10
...
sum[7] = 5*7 - 10 = 25
sum[8] = 0*8 - (-25) = 25
sum[9] = 0*9 - (-25) = 25
Để đạt được các giá trị BIT1 và BIT2 mong muốn cho bản cập nhật phạm vi trước đó, chúng tôi thực hiện 3 cập nhật phạm vi:
Chúng tôi cần thực hiện cập nhật phạm vi +5 cho các chỉ số 3..7 cho BIT1.
Chúng tôi cần thực hiện cập nhật phạm vi +10 cho các chỉ số 3..7 cho BIT2.
Chúng ta cần thực hiện cập nhật phạm vi từ -25 đến các chỉ số 8..9 cho BIT2.
Bây giờ hãy thực hiện một chuyển đổi nữa. Thay vì lưu trữ các giá trị được hiển thị ở trên cho BIT1 và BIT2, chúng tôi thực sự lưu trữ các khoản tiền tích lũy của chúng. Điều này cho phép chúng tôi thực hiện 3 cập nhật phạm vi ở trên bằng cách thực hiện 4 cập nhật cho các khoản tiền tích lũy:
BIT1sum[3] += 5
BIT1sum[8] -= 5
BIT2sum[3] += 10
BIT2sum[8] -= 35
Nói chung, thuật toán để thêm giá trị v vào phạm vi [i..j] sẽ là:
BIT1sum[i] += v
BIT1sum[j+1] -= v
BIT2sum[i] += v * (i-1)
BIT2sum[j+1] -= v * j
trong đó cú pháp + = và - = chỉ đơn giản là cập nhật cấu trúc dữ liệu tổng tích lũy BIT với giá trị dương hoặc âm tại chỉ mục đó. Lưu ý rằng khi bạn cập nhật tổng tích lũy BIT tại một chỉ mục, nó hoàn toàn ảnh hưởng đến tất cả các chỉ số ở bên phải của chỉ mục đó. Ví dụ:
0 0 0 0 0 0 0 0 0 0 (original)
BITsum[3] += 5
0 0 0 5 5 5 5 5 5 5 (after updating [3])
BITsum[8] -= 5
0 0 0 5 5 5 5 5 0 0 (after updating [8])
O ( nhật kýn )
sum[i] = BIT1[i] * i - BIT2[i]
gì? Nó có vẻ hoạt động nhưng có vẻ rất độc đoán ... cái nhìn sâu sắc nào cho phép bạn đến với điều này?