Несогласованные поддеревья. Реализация массового обновления — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Массовое обновление на отрезке)
(Массовое обновление на отрезке)
Строка 10: Строка 10:
  
 
Если операция <tex>\odot</tex> не коммутативна, то при запросах нужно, во-первых, раздать детям несогласованность, во-вторых, вызвать функцию от детей и, в-третьих, пересчитать свое значение. Очень важно выполнить все три пункта.  
 
Если операция <tex>\odot</tex> не коммутативна, то при запросах нужно, во-первых, раздать детям несогласованность, во-вторых, вызвать функцию от детей и, в-третьих, пересчитать свое значение. Очень важно выполнить все три пункта.  
==Массовое обновление на отрезке==
+
==Пример==
  
Для реализаций операций на отрезке нам потребует
+
Рассмотрим массовые операции на отрезке на примере задачи "Прибавление на отрезке". При этом мы должны отвечать на запрос минимума на отрезке.
Массовые операции на отрезке рассмотрим на примере минимума на отрезке и прибавления на отрезке.
 
  
Пусть дерево отрезков хранится в массиве <tex>T</tex>. Для реализации массового обновления будем хранить дополнительный массив несогласованностей <tex>d</tex>. Истинные значения <tex>T'[v] = T[v] + d[v]</tex>.
+
Для эффективной реализаций будем использовать описанную выше структуру {{---}} несогласованные поддеревья. В каждой вершине, помимо непосредственно суммы, храним несогласованность {{---}} сколько необходимо прибавить ко всем числам этого отрезка(соответственно при запросе минимума истинный минимум на отрезке при корректной несогласованности {{---}} сумма несогласованности и значения в вершине). Тем самым мы сможем обрабатывать запрос прибавления на любом подотрезке эффективно, вместо того чтобы изменять все <tex>O(N)</tex>значений.
 +
 
 +
Если теперь приходит запрос минимального значения на отрезке, то нам достаточно спуститься по дереву, "протолкнув" все встреченные по пути несогласованности, записанные в вершинах дерева.
  
 
==Псевдокод==
 
==Псевдокод==

Версия 16:30, 28 мая 2012

Дерево отрезков позволяет отвечать на запросы к целым отрезкам подряд идущих элементов, причем за то же время [math]O(\log n)[/math].

Несогласованные поддеревья

Сперва рассмотрим так называемые несогласованные поддеревья.

В несогласованном поддереве дерева отрезков в вершинах хранятся не истинные значения сумм (по операции [math]\oplus[/math]) на отрезках, однако гарантируется, что на запрос они отвечают верно. При этом в корне поддерева, которому соответствует отрезок [math]a_i..a_j[/math] хранится несогласованность [math]d[/math]. Если в вершине хранится истинное значение суммы, то [math]d = \perp[/math] — нейтральный элемент относительно операции [math]\odot[/math] (например 0 для прибавления). Для реализации вторая операция должна быть ассоциативной, и операций должны удовлетворять свойству дистрибутивность:

  1. [math]a \odot (b \odot c) = (a \odot b) \odot c[/math]
  2. [math](a \oplus b) \odot c = (a \odot c) \oplus (b \odot c)[/math]
  3. [math]c \odot (a \oplus b) = (c \odot a) \oplus (c \odot b)[/math]

Если операция [math]\odot[/math] не коммутативна, то при запросах нужно, во-первых, раздать детям несогласованность, во-вторых, вызвать функцию от детей и, в-третьих, пересчитать свое значение. Очень важно выполнить все три пункта.

Пример

Рассмотрим массовые операции на отрезке на примере задачи "Прибавление на отрезке". При этом мы должны отвечать на запрос минимума на отрезке.

Для эффективной реализаций будем использовать описанную выше структуру — несогласованные поддеревья. В каждой вершине, помимо непосредственно суммы, храним несогласованность — сколько необходимо прибавить ко всем числам этого отрезка(соответственно при запросе минимума истинный минимум на отрезке при корректной несогласованности — сумма несогласованности и значения в вершине). Тем самым мы сможем обрабатывать запрос прибавления на любом подотрезке эффективно, вместо того чтобы изменять все [math]O(N)[/math]значений.

Если теперь приходит запрос минимального значения на отрезке, то нам достаточно спуститься по дереву, "протолкнув" все встреченные по пути несогласованности, записанные в вершинах дерева.

Псевдокод

Нумерация массива с нуля, то есть корень дерева — 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])
}

Ссылки

MAXimal :: algo :: Дерево отрезков

Дерево отрезков — Википедия