Городские фонари: сколько света на проспекте?

тема: Fenwick/Segment tree · уровень: продвинутый

Условие

В городе на одной длинной улице стоят фонари, пронумерованные слева направо от 1 до N. У каждого фонаря есть текущая «яркость» (целое число). Диспетчерская получает команды двух типов:

Нужно быстро обрабатывать все команды.

Формат ввода

Первая строка: целое число N — количество фонарей. Вторая строка: N целых чисел a1, a2, ..., aN — начальные яркости. Третья строка: целое число Q — количество команд. Далее идут Q строк, каждая — одна команда:

Формат вывода

Для каждой команды SUM выведите одно целое число в отдельной строке.

Ограничения

Пример

Ввод:

5
1 2 3 4 5
6
SUM 2 4
SET 3 10
SUM 1 3
SUM 3 3
SET 5 0
SUM 4 5

Вывод:

9
13
10
4

Как решать — идея подхода

Приём: Дерево Фенвика

Главная трудность в том, что после SET обычные префиксные суммы перестают быть удобными: изменение одного фонаря пришлось бы распространять на все следующие суммы. Пересчитывать их каждый раз — долго.

Подходит дерево Фенвика: массив fen, где каждая ячейка хранит сумму небольшого блока. Размер блока определяется младшим установленным битом номера: i & -i. Благодаря этому и изменение, и поиск суммы префикса проходят только по O(log N) ячейкам.

Сумма на отрезке выражается через две префиксные суммы:

sum(l..r) = pref(r) - pref(l - 1)

Префиксная сумма в дереве находится движением влево: после добавления fen[i] переходите к i -= i & -i. При обновлении, наоборот, двигайтесь вправо: i += i & -i.

Сложность: построение простым добавлением — O(N log N), каждая команда — O(log N). Память — O(N).

Частая ошибка: при SET добавить в дерево x, а не разницу x - a[i]. Тогда старое значение останется в суммах, и ответы станут завышенными.

Решить задачу с автопроверкой на Python →

Куда дальше