Несогласованные поддеревья. Реализация массового обновления — различия между версиями
Rybak (обсуждение | вклад) |
|||
| Строка 14: | Строка 14: | ||
get_min(v, l, r) { | get_min(v, l, r) { | ||
// v - текущая вершина, l и r - границы запроса | // v - текущая вершина, l и r - границы запроса | ||
| − | if (отрезок | + | if (отрезок соответствующий v не пересекается с [l, r]) |
return inf // бесконечность - нейтральный элемент относительно min | return inf // бесконечность - нейтральный элемент относительно min | ||
| − | if (отрезок | + | if (отрезок соответствующий v содержится в [l, r]) |
return tree[v] + d[v] | return tree[v] + d[v] | ||
// Раздаем детям | // Раздаем детям | ||
| − | d[2*v+1] = d[2*v+1] + d[v] | + | d[2 * v + 1] = d[2 * v + 1] + d[v] |
| − | d[2*v+2] = d[2*v+2] + d[v] | + | d[2 * v + 2] = d[2 * v + 2] + d[v] |
d[v] = 0 | d[v] = 0 | ||
// Вызываем функцию от детей | // Вызываем функцию от детей | ||
| − | ans = min(get_min(2*v+1, l, r), get_min(2*v+2, l, r)) | + | 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]) | + | T[v] = min(T[2 * v + 1] + d[2 * v + 1], T[2 * v + 2] + d[2 * v + 2]) |
return ans | return ans | ||
} | } | ||
| Строка 38: | Строка 38: | ||
} | } | ||
// Раздаем детям | // Раздаем детям | ||
| − | d[2*v+1] = d[2*v+1] + d[v] | + | d[2 * v + 1] = d[2 * v + 1] + d[v] |
| − | d[2*v+2] = d[2*v+2] + d[v] | + | d[2 * v + 2] = d[2 * v + 2] + d[v] |
d[v] = 0 | d[v] = 0 | ||
// Вызываем функцию от детей | // Вызываем функцию от детей | ||
| − | update(2*v+1, l, r, x) | + | update(2 * v + 1, l, r, x) |
| − | update(2*v+2, 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]) | + | T[v] = min(T[2 * v + 1] + d[2 * v + 1], T[2 * v + 2] + d[2 * v + 2]) |
| − | |||
} | } | ||
Версия 23:55, 22 января 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])
}