Реализация запроса в дереве отрезков снизу — различия между версиями
Martoon (обсуждение | вклад) м (→Псевдокод) |
Shersh (обсуждение | вклад) |
||
Строка 8: | Строка 8: | ||
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат. | # Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат. | ||
− | [[Файл:Range_tree_down_request1.gif| | + | {| cellpadding="10" |
− | + | | '''Реализация запроса снизу вверх''' || '''Ещё один пример''' | |
− | [[Файл:Range_tree_down_request2.gif| | + | |- |
− | + | | [[Файл:Range_tree_down_request1.gif|550px|]] || [[Файл:Range_tree_down_request2.gif|550px]] | |
− | + | |} | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==Псевдокод== | ==Псевдокод== |
Версия 13:10, 11 июня 2013
Алгоритм
Реализация запроса снизу вверх в дереве отрезков является, в отличие от реализации запроса сверху вниз, итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее a b.
Построим дерево отрезков и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:
- Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от вклада ненужного нам поддерева.
- Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.
- Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.
Реализация запроса снизу вверх | Ещё один пример |
Псевдокод
Пусть результат считаем на отрезке [left, right]. При этом значения left и right, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные left_res и right_res будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого.
query(left, right) left_res = neutral; right_res = neutral; while left < right if left mod 2 == 0 left_res = left_resdata[left]; left = left div 2; if right mod 2 == 1 right_res = data[right] right_res; right = (right - 1) div 2; if left == right left_res = left_res data[left]; return left_res right_res;