Все темы
144

Текущие суммы, которые всё время меняются

Tier 1Закрыто

Где применяется

1. Задача

Последний раздел курса собирает вместе многое из того, что ты уже построил. Дерево Фенвика и дерево отрезков соединяют массив, дерево и префиксные суммы. Они отвечают на вопросы про отрезок массива, когда данные всё время меняются.

Пример. Игровой рейтинг всю ночь получает очки игроков, по одному результату за раз. Игрок спрашивает: «Сколько человек сейчас набрали меньше меня?» Ответ нужен быстро, и он должен оставаться верным, пока приходят новые очки.

В уроке 24 были префиксные суммы. Один раз считаешь накопленные итоги, и потом любой вопрос «сумма первых i» решается одним чтением из массива, за O(1). Но стоит поменять одно значение, и все итоги после него становятся неверными. Массив итогов приходится пересчитывать, каждый раз за O(n).

Когда чтения и изменения идут вперемешку, а массив большой, пересчёт съедает всё время. Миллион изменений в массиве из миллиона чисел даёт миллион пересчётов по миллиону шагов. Нужна структура, где дёшево и изменить значение, и спросить сумму.

Этот шаг из платной части

Бесплатные шаги в начале курса (их 33) открыты всем: урок, задача и тесты. Этот шаг открывается с полным доступом. Начни с бесплатного аккаунта и бесплатных шагов.

Завести бесплатный аккаунтПосмотреть, что входит
Сумма на отрезке и точечное изменение в дереве отрезков
arr = [2, 5, 1, 4, 3, 6]; query(1, 4); update(2, 3)
в узле сумма его отрезка, над узлом сам отрезок
arr
2
5
1
4
3
6
query = 1..4sum = 0

Каждый узел хранит сумму своего отрезка, дерево построено один раз из [2, 5, 1, 4, 3, 6]. Ищем сумму arr[1..4].

Гонка скорости
40 сумм на префиксе и 10 изменений в одних и тех же 40 числах

Столбики: 40 значений, которые меняются с каждым изменением. У дерева Фенвика подсвеченный столбик означает ячейку дерева на этой позиции. Запросов n, изменений n / 4, и здесь, и в таблице ниже.

Одна операция: одно чтение или одна запись ячейки. За каждый кадр все дорожки делают одинаковое число операций, поэтому медленная отстаёт.

Обычный массив O(n·q)
операций: 0
Дерево Фенвика O(n + q log n)
операций: 0

 

А если чисел больше

Операции для n чисел и примерное время при 100 миллионах простых операций в секунду. Это оценка по тому же счёту, а не замер.

n = 1 000
Обычный массив500,8 тыс. · 5 мс
Дерево Фенвика9,5 тыс. · меньше 1 мс
n = 100 000
Обычный массив5 млрд · 50 с
Дерево Фенвика1,4 млн · 14 мс
n = 10 000 000
Обычный массив50 трлн · 5,8 дн.
Дерево Фенвика194,4 млн · 1,9 с

Как узнать

Дерево Фенвика / дерево отрезков (Fenwick tree / segment tree)

Эти слова в условии значат этот паттерн

  • сумма или запрос на отрезке с точечными обновлениями вперемешку
  • живой лидерборд или ранг, пока баллы меняются
  • подсчёт инверсий или сколько более ранних значений больше
  • запросы на отрезке, пока данные продолжают меняться

Похоже, но не то

  • Префиксные суммы (Prefix sums)

    Префиксные суммы читаются быстрее, но ломаются при любом изменении. Здесь платят log n за право менять.

  • Массив разностей (Difference array)

    Он принимает много изменений на отрезках и одно чтение в конце. Здесь чтения и записи перемешаны.

  • Линия развёртки (подсчёт событий) (Sweep line (event counting))

    Развёртка идёт по событиям в порядке сортировки и не оглядывается. Здесь запросы приходят в любом порядке.

  • Бинарный поиск (массив) (Binary search (array))

    Оба делят отрезок пополам на каждом шаге. Один ищет значение, другой сворачивает отрезок.

n до 1e6 и q смешанных операций дают O((n + q) log n). Память O(n) для дерева Фенвика.

На LeetCode

Задачи, где меняют отдельные значения и между этим спрашивают суммы на префиксе или отрезке, и задачи на подсчёт, например сколько меньших чисел было раньше. Дерево Фенвика делает обе операции за O(log n), а подсчёт идёт через прибавление 1 в позиции каждого значения.

Мы используем необходимые куки для работы сайта (вход и язык). Если ты согласишься, мы также загрузим Google Analytics, чтобы видеть, какие страницы читают, и Google reCAPTCHA для защиты форм обратной связи и сообщений об ошибке от спама. Политика конфиденциальности