Оновлення діапазону + запит діапазону з бінарними індексованими деревами


10

Я намагаюся зрозуміти, як бінарні індексовані дерева (fenwick дерева) можуть бути модифіковані для обробки запитів діапазону та оновлень діапазону.

Я знайшов такі джерела:

http://kartikkukreja.wordpress.com/2013/12/02/range-updates-with-bit-fenwick-tree/ http://programmingcontests.quora.com/Tutorial-Range-Updates-in-Fenwick-Tree http : //apps.topcoder.com/forums/? module = Thread & threadID = 756271 & start = 0 & mc = 4 # 1579597

Але навіть прочитавши їх усі, я не міг зрозуміти, яка мета другого бінарного індексованого дерева чи що воно робить.

Чи не може хтось пояснити мені, як модифіковане двійкове дерево з індексованим виправленням?

Відповіді:


9

Припустимо, у вас був порожній масив:

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, легко вО(журналн) час.


Якою була ваша початкова мотивація у створенні BIT2 та у подальшому sum[i] = BIT1[i] * i - BIT2[i]? Це, здається, працює, але це здається таким довільним ... яке розуміння дозволяє вам дійти до цього?
1110101001

3
Ну, я не вигадав цей алгоритм. Я читав це так само, як ти. Але слід зауважити, що додаючи оновлення діапазону, ваші сукупні суми стають зростаючою послідовністю (5, 10, 15, 20, ...). Біти не зберігають такі послідовності. Але якщо ви зберігаєте константу (5) у BIT і множите значення BIT на індекс, ви отримуєте зростаючу послідовність, як і те, що ви хочете. Однак вам потрібно зафіксувати початок і кінець послідовності. Саме для цього і друге дерево.
JS1

Добре в цілому, але я вважаю заплутаним те, що ви написали "Замість того, щоб зберігати вказані вище значення для BIT1 і BIT2, ми фактично зберігаємо їх сукупні суми" - я б сказав, що ви насправді робите навпаки, тобто зберігаєте дельти .
j_random_hacker
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.