Несогласованные поддеревья. Реализация массового обновления — различия между версиями
Gr1n (обсуждение | вклад) |
|||
Строка 1: | Строка 1: | ||
Дерево отрезков позволяет отвечать на запросы к целым отрезкам подряд идущих элементов, причем за то же время <tex>O(\log n)</tex>. | Дерево отрезков позволяет отвечать на запросы к целым отрезкам подряд идущих элементов, причем за то же время <tex>O(\log n)</tex>. | ||
− | + | ==Несогласованные поддеревья== | |
В несогласованном поддереве дерева отрезков в вершинах хранятся не истинные значения сумм (по операции <tex>\oplus</tex>) на отрезках. При этом в корне поддерева, которому соответствует отрезок <tex>a_i..a_j</tex> хранится несогласованность <tex>d</tex>. Если в вершине хранится истинное значение суммы, то <tex>d = \perp</tex> {{---}} нейтральный элемент относительно операции <tex>\odot</tex> (например 0 для прибавления). Для реализации вторая операция должна быть ассоциативной, и должен выполняться распределительный закон с <tex>\oplus</tex>: | В несогласованном поддереве дерева отрезков в вершинах хранятся не истинные значения сумм (по операции <tex>\oplus</tex>) на отрезках. При этом в корне поддерева, которому соответствует отрезок <tex>a_i..a_j</tex> хранится несогласованность <tex>d</tex>. Если в вершине хранится истинное значение суммы, то <tex>d = \perp</tex> {{---}} нейтральный элемент относительно операции <tex>\odot</tex> (например 0 для прибавления). Для реализации вторая операция должна быть ассоциативной, и должен выполняться распределительный закон с <tex>\oplus</tex>: | ||
Строка 13: | Строка 13: | ||
Пусть дерево отрезков хранится в массиве <tex>T</tex>. Для реализации массового обновления будем хранить дополнительный массив несогласованностей <tex>d</tex>. Истинные значения <tex>T'[v] = T[v] + d[v]</tex>. | Пусть дерево отрезков хранится в массиве <tex>T</tex>. Для реализации массового обновления будем хранить дополнительный массив несогласованностей <tex>d</tex>. Истинные значения <tex>T'[v] = T[v] + d[v]</tex>. | ||
− | + | ==Псевдокод== | |
Нумерация массива с нуля, то есть корень дерева {{---}} T[0]. | Нумерация массива с нуля, то есть корень дерева {{---}} T[0]. | ||
Строка 52: | Строка 52: | ||
T[v] = min(T[2 * v + 1] + d[2 * v + 1], T[2 * v + 2] + d[2 * v + 2]) | T[v] = min(T[2 * v + 1] + d[2 * v + 1], T[2 * v + 2] + d[2 * v + 2]) | ||
} | } | ||
+ | |||
+ | ==Ссылки== | ||
+ | |||
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Дерево отрезков]] | [[Категория: Дерево отрезков]] |
Версия 15:51, 28 мая 2012
Дерево отрезков позволяет отвечать на запросы к целым отрезкам подряд идущих элементов, причем за то же время
.Несогласованные поддеревья
В несогласованном поддереве дерева отрезков в вершинах хранятся не истинные значения сумм (по операции
) на отрезках. При этом в корне поддерева, которому соответствует отрезок хранится несогласованность . Если в вершине хранится истинное значение суммы, то — нейтральный элемент относительно операции (например 0 для прибавления). Для реализации вторая операция должна быть ассоциативной, и должен выполняться распределительный закон с :Если операция
не коммутативна, то при запросах нужно, во-первых, раздать детям несогласованность, во-вторых, вызвать функцию от детей и, в-третьих, пересчитать свое значение. Очень важно выполнить все три пункта.Массовые операции на отрезке рассмотрим на примере минимума на отрезке и прибавления на отрезке.
Пусть дерево отрезков хранится в массиве
. Для реализации массового обновления будем хранить дополнительный массив несогласованностей . Истинные значения .Псевдокод
Нумерация массива с нуля, то есть корень дерева — T[0].
get_min(v, l, r) { // v - текущая вершина, l и r - границы запроса if (отрезок соответствующий v не пересекается с [l, r]) return inf // бесконечность - нейтральный элемент относительно min if (отрезок соответствующий v содержится в [l, r]) return tree[v] + d[v] // Раздаем детям d[2 * v + 1] = d[2 * v + 1] + d[v] d[2 * v + 2] = d[2 * v + 2] + d[v] d[v] = 0 // Вызываем функцию от детей ans = min(get_min(2 * v + 1, l, r), get_min(2 * v + 2, l, r)) // Пересчитываем свое значение T[v] = min(T[2 * v + 1] + d[2 * v + 1], T[2 * v + 2] + d[2 * v + 2]) return ans } update(v, l, r, x) { // x - сколько нужно прибавить на отрезке if (отрезок соответственный v не пересекается с [l, r]) return if (отрезок соответственный v содержится в [l, r]) { d[v] = d[v] + x return } // Раздаем детям d[2 * v + 1] = d[2 * v + 1] + d[v] d[2 * v + 2] = d[2 * v + 2] + d[v] d[v] = 0 // Вызываем функцию от детей update(2 * v + 1, l, r, x) update(2 * v + 2, l, r, x) // Пересчитываем свое значение T[v] = min(T[2 * v + 1] + d[2 * v + 1], T[2 * v + 2] + d[2 * v + 2]) }