Припустимо, у вас був порожній масив:
0 0 0 0 0 0 0 0 0 0 (array)
0 0 0 0 0 0 0 0 0 0 (cumulative sums)
І ви хочете оновити діапазон від +5 до [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)
Як ви могли зберігати бажані сукупні суми за допомогою двох двійкових індексованих дерев?
Хитрість полягає у використанні двох бінарних індексованих дерев, BIT1 та BIT2, де сукупна сума обчислюється з їх вмісту. У цьому прикладі, ось що ми зберегли б у двох деревах:
0 0 0 5 5 5 5 5 0 0 (BIT1)
0 0 0 10 10 10 10 10 -25 -25 (BIT2)
Щоб знайти sum[i]
, ви обчислите це:
sum[i] = BIT1[i] * i - BIT2[i]
Наприклад:
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
Для досягнення бажаних значень BIT1 та BIT2 для попереднього оновлення діапазону ми робимо 3 оновлення діапазону:
Нам потрібно зробити оновлення діапазону від +5 до індексів 3..7 для BIT1.
Нам потрібно здійснити оновлення діапазону від +10 до індексів 3..7 для BIT2.
Нам потрібно зробити оновлення діапазону від -25 до індексів 8..9 для BIT2.
Тепер давайте зробимо ще одну трансформацію. Замість того, щоб зберігати наведені вище значення для BIT1 і BIT2, ми фактично зберігаємо їх сукупні суми. Це дозволяє нам оновлювати 3 діапазони вище, вносячи 4 оновлення сукупних сум:
BIT1sum[3] += 5
BIT1sum[8] -= 5
BIT2sum[3] += 10
BIT2sum[8] -= 35
Загалом алгоритм додавання значення v до діапазону [i..j] був би:
BIT1sum[i] += v
BIT1sum[j+1] -= v
BIT2sum[i] += v * (i-1)
BIT2sum[j+1] -= v * j
де синтаксис + = і - = означає просто оновити структуру даних сукупної суми BIT з позитивним або негативним значенням при цьому індексі. Зауважте, що коли ви оновлюєте сукупну суму BIT в індексі, це неявно впливає на всі індекси праворуч від цього індексу. Наприклад:
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])
Дерева Fenwick зберігають суми у бінарному дереві. Провести оновлення, показані вище на дереві Fenwick, легко вO ( журналn ) час.
sum[i] = BIT1[i] * i - BIT2[i]
? Це, здається, працює, але це здається таким довільним ... яке розуміння дозволяє вам дійти до цього?