Зачем нужно дерево отрезков
Задача, в которой запросы и изменения перемешаны, и почему префиксные суммы со sparse table на ней ломаются.
2 мин
Есть массив. Приходят запросы двух видов, вперемешку:
- спросить что-то про отрезок — сумму, минимум, максимум;
- изменить элемент.
Каждый по отдельности решается легко. Вместе — нет.
Что умеют более простые структуры
Префиксные суммы отвечают на запрос суммы за после предподсчёта. Но изменение одного элемента портит все префиксы правее него: пересчёт стоит .
Sparse table отвечает за на минимум и максимум, но перестроить её после изменения стоит .
Обычный массив, наоборот, меняется за , а запрос требует прохода по отрезку — снова .
| структура | запрос | изменение |
|---|---|---|
| массив | ||
| префиксные суммы | ||
| sparse table | ||
| дерево отрезков |
Дерево отрезков не выигрывает ни в одной строке по отдельности. Оно выигрывает, когда обе операции нужны одновременно: запросов вперемешку с изменениями — это операций вместо .
Когда дерево не нужно
Если изменений нет вовсе, дерево избыточно. Берите префиксные суммы для сумм и sparse table для минимума с максимумом: они проще и быстрее по константе.
Исключение — память: sparse table занимает , дерево отрезков . При разница между 68 мегабайтами и 8 бывает решающей.
Если, наоборот, нет запросов на отрезке, а только на весь массив, хватит нескольких переменных.
Что дерево умеет сверх этого
Список операций, ради которых его берут даже там, где хватило бы префиксных сумм:
- операция на отрезке: прибавить, присвоить, применить XOR ко всем элементам сразу;
- вопрос «где»: найти -й ноль, первый элемент не меньше — за один логарифм, а не за два;
- составной ответ: минимум вместе с количеством минимумов, максимальная сумма подотрезка, длина серии.
Каждой из этих возможностей посвящена отдельная статья раздела. Начать стоит с устройства.