Возможно ли построить дерево Фенвика в O (n)?

Fenwick tree - это структура данных, которая позволяет выполнять два вида операций (вы можете увеличить ее с помощью большего количества операций):

  • обновление точки update(index, value)
  • префикс sum query(index)

Обе операции находятся в O(log(n)), где n - размер массива. У меня нет проблем с пониманием того, как выполнять обе операции и логику, лежащую в их основе.


Мой вопрос в том, как я могу инициализировать дерево Fenwick из массива. Ясно, что я могу достичь этого в O(nlog(n)), вызывая n times update(i, arr[i]), но есть способ инициализировать его в O(n).


Почему я спрашиваю об этом, если википедия говорит, что вы можете инициализировать в nlog(n)? Поскольку статья настолько рудиментарна, что я не уверен, что это лучшая сложность, которую можно достичь. Кроме того, рисование параллелей с наивным созданием кучи, которое делается путем заполнения кучи один за другим и может быть достигнуто в O(nlog(n)) по сравнению с умной инициализацией кучи в O(n), дает мне надежду на то, что что-то подобное можно сделать в дереве Фенвика.

Ответ 1

[РЕДАКТИРОВАТЬ: У меня были вещи "вверх тормашками" - исправлено сейчас!]

Да. Перебирайте элементы массива n в порядке возрастания индекса, всегда добавляя сумму только к следующему наименьшему индексу, к которому он должен быть добавлен, а не ко всем из них:

for i = 1 to n:
    j = i + (i & -i)     # Finds next higher index that this value should contribute to
    if j <= n:
        x[j] += x[i]

Это работает, потому что, хотя каждое значение вносит несколько сумм диапазона, после обработки самой нижней суммы диапазона, которую значение вносит (что фактически не требует "обработки", поскольку сумма уже там), нам больше не нужно поддерживать его отдельная идентификация - ее можно смело объединить со всеми другими значениями, которые вносят вклад в оставшиеся суммы сумм.

TTBOMK этот алгоритм "новый" - но тогда я не выглядел очень тяжело;)