Реализация запроса в дереве отрезков сверху — различия между версиями
Gr1n (обсуждение | вклад) |
Gr1n (обсуждение | вклад) (→Алгоритм) |
||
Строка 3: | Строка 3: | ||
==Алгоритм== | ==Алгоритм== | ||
− | + | Рассмотрим данный алгоритм на примере задачи RSQ(запрос суммы на отрезке), то есть пусть есть уже построенное дерево отрезков и задача найти сумму на отрезке <tex>[a .. b]</tex>. | |
[[Файл:123.jpg|right|380px|thumb|Пример дерева отрезков для вычисления сумм]] | [[Файл:123.jpg|right|380px|thumb|Пример дерева отрезков для вычисления сумм]] | ||
− | + | Будем передавать в качестве параметров рекурсий следующие переменные: | |
+ | * <tex>ver</tex> {{---}} номер(в массиве с деревом отрезков) текущей вершины дерева. | ||
+ | * <tex>l</tex>, <tex>r</tex> {{---}} левая и правая границы отрезков, за которые "отвечает" наша вершина. | ||
+ | * <tex>a</tex>, <tex>b</tex> {{---}} левая и правая границы запрашиваемого отрезка. | ||
− | Запустим рекурсивную процедуру от всего отрезка. | + | Запустим рекурсивную процедуру от всего отрезка(то есть от корневой вершины). |
− | + | Для текущего состояния проверяем следующие условия : | |
− | * | + | * Если текущий отрезок не пересекается с искомым, то возвращаем нулевое значение. |
− | ''Например'': | + | ''Например'': текущий <tex>[1..2]</tex>, а искомый <tex>[3 .. 4]</tex>; |
− | текущий <tex>[ | + | * Текущий отрезок совпадает, то возвращаем значение в текущей вершине. |
+ | ''Например'': текущий и искомый <tex>[2..3]</tex>; | ||
− | * | + | * Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом сумма на текущем отрезке равна сумме результатов функций, запущенных от детей. |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==Пример== | ==Пример== |
Версия 18:34, 20 апреля 2012
Содержание
Описание
Данная рекурсивная операция позволяет выполнять запросы на дереве отрезков, причем алгоритм запускается от корня и рекурсивно идет сверху вниз.
Алгоритм
Рассмотрим данный алгоритм на примере задачи RSQ(запрос суммы на отрезке), то есть пусть есть уже построенное дерево отрезков и задача найти сумму на отрезке
.Будем передавать в качестве параметров рекурсий следующие переменные:
- — номер(в массиве с деревом отрезков) текущей вершины дерева.
- , — левая и правая границы отрезков, за которые "отвечает" наша вершина.
- , — левая и правая границы запрашиваемого отрезка.
Запустим рекурсивную процедуру от всего отрезка(то есть от корневой вершины).
Для текущего состояния проверяем следующие условия :
- Если текущий отрезок не пересекается с искомым, то возвращаем нулевое значение.
Например: текущий
, а искомый ;- Текущий отрезок совпадает, то возвращаем значение в текущей вершине.
Например: текущий и искомый
;- Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом сумма на текущем отрезке равна сумме результатов функций, запущенных от детей.
Пример
Рассмотрим работу программы на дереве отрезков для элементов
. Пусть запрашиваемая сумма - это отрезок .- Текущий отрезок , он больше => переходим по рекурсивным вызовам на и
- выходит за границы , выходит за границы => переходим по рекурсивным вызовам на , и , .
- выходит за границы => переходим в листья 1, 2; целиком внутри => возвращаем значение в ;
не пересекается с => возвращаем нулевое значение, выходит за границы => переходим к листьям 5 и 6
- лист 6 не пересекается с отрезком => возвращаем нулевое значение, лист 5 целиков внутри => возвращаем значение в листе 5.
Реализация
int sum (int v, int tl, int tr, int l, int r)
{
if ([l,r]
[tl, tr]) =
return 0;
if ([l,r] = [tl, tr])
return t[v];
int tm = (tl + tr) / 2;
return sum (v*2, tl, tm, l, min(r,tm))
+ sum (v*2+1, tm+1, tr, max(l,tm+1), r);
}