Реализация запроса в дереве отрезков снизу — различия между версиями
Nastya (обсуждение | вклад) (→Псевдокод) |
Nastya (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
==Алгоритм== | ==Алгоритм== | ||
− | Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее | + | Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее <tex>a \circ b</tex>. |
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа: | [[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа: | ||
Строка 22: | Строка 22: | ||
==Псевдокод== | ==Псевдокод== | ||
− | Пусть результат считаем на отрезке [left, right]. При этом значения left и right, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные | + | Пусть результат считаем на отрезке [<tex> left, right </tex>]. При этом значения <tex>left</tex> и <tex>right</tex>, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные <tex>left</tex>_<tex>res</tex> и <tex>right</tex>_<tex>res</tex> будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. |
'''int''' query(left : '''int''', right : '''int'''): | '''int''' query(left : '''int''', right : '''int'''): |
Версия 10:45, 13 июня 2014
Алгоритм
Реализация запроса снизу вверх в дереве отрезков является, в отличие от реализации запроса сверху вниз, итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее .
Построим дерево отрезков и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:
- Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от вклада ненужного нам поддерева.
- Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.
- Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.
Реализация запроса снизу вверх | Ещё один пример |
Псевдокод
Пусть результат считаем на отрезке [
]. При этом значения и , передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные _ и _ будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого.int query(left : int, right : int): 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