Binary Indexed Tree (Дерево Фенвика) — об обновлении

Недавно я изучил структуру данных Дерево Фенвика (двоичное индексированное дерево).

При запросе я могу понять, зачем вычитать (idx и -idx). Однако я не могу понять, зачем добавлять (idx и -idx) при обновлении значения.

Другими словами, я знаю, что мы должны обновить все интервалы, на которые повлияет обновление какого-то одного элемента x, и я знаю, что BIT[x] обновляется первым, но не могу понять, почему следующий индекс должен быть обновлен. БИТ [x + (x & -x)]

Спасибо.


person Haidar Abboud    schedule 08.08.2012    source источник
comment
Нарисуйте простой пример на бумаге   -  person BlueRaja - Danny Pflughoeft    schedule 09.08.2012


Ответы (1)


Вот хорошее объяснение: http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees

Ключевая идея состоит в том, что если f(i) — это частота с индексом i, то t(i) — это кумулятивная частота для всех (i — (r — 1)) .. i, где r — наименьший установленный бит в i. Вы можете рассчитать r как r = i & -i.

[EDIT: выше я неправильно написал (r - 1) как (2 ^ r - 1).]

Например, если i = 12 = 1100_2, то r = 100_2 и t(i) = f(1001_2) + f(1010_2) + f(1011_2) + f(1100_2) = f(9) + f(10) + f(11) + f(12).

При вычислении кумулятивной частоты от 0 .. i вы, по существу, суммируете значения t в i, i с удаленным наименьшим установленным битом, i с удаленными наименьшими двумя установленными битами, ... и так далее, пока не закончатся биты.

Например, если i = 12 = 1100_2, нам нужно t(1100_2) + t(1000_2).

Следовательно, если вы измените значение в f(i), вы должны изменить все затронутые значения t. Это t(i), t(i + r), 2t(i + r), 4t(i + r), ... и так далее, пока мы не превысим последний индекс. Именно эти затронутые значения t мы будем исследовать для любого расчета кумулятивной частоты для индекса j >= i.

[EDIT: исправлена ​​последовательность «затронутых значений t» в последнем абзаце в ответ на исправление j_random_hacker.]

person Rafe    schedule 09.08.2012
comment
Это t(i), t(i + r), t(i + 2r), t(i + 4r) не совсем правильно — после каждого добавления младшего бита 1 вам нужно начинать заново, что может сделать более поздние прыжки больше, когда есть переносы. Например. посмотрите на суммы, которые включают 7 на изображении 1.3 вашей ссылки, а именно 7, 8, 16. - person j_random_hacker; 26.12.2012
comment
@j_random_hacker: ты совершенно прав — хорошо замечено! Я соответствующим образом отредактировал свое объяснение. - person Rafe; 27.12.2012
comment
Спасибо, но все равно не то! Я не думаю, что для него обязательно должно быть хорошее выражение в закрытой форме, его проще всего описать (и реализовать!) Рекурсивно: t(i), t(f(i)), t(f(f(i))) , ..., где f(x) = x + младший_бит(x). - person j_random_hacker; 27.12.2012