Реализация запроса в дереве отрезков снизу — различия между версиями
Lirik (обсуждение | вклад) |
Lirik (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
− | + | ==Алгоритм== | |
− | + | Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее a <tex> \circ </tex> b. | |
− | + | [[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа: | |
+ | 1. Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей(является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от вклада ненужного нам поддерева. | ||
+ | 2. Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1), пока границы не пересекутся. | ||
+ | 3. Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат. | ||
− | [[ | + | [[Файл:ДО_снизу_вверх.png|800px|Реализация запроса снизу вверх]] |
==Псевдокод== | ==Псевдокод== | ||
− | Пусть | + | Пусть результат считаем на отрезке [left, right]. При этом значения передающиеся в функцию left и right должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). |
query(left, right) | query(left, right) | ||
− | result = neutral; | + | result = neutral; |
− | '''while''' left < right | + | '''while''' left < right |
− | '''if''' left mod 2 == 0 | + | '''if''' left mod 2 == 0 |
− | result = result <tex> \circ </tex> data[left]; | + | result = result <tex> \circ </tex> data[left]; |
left = left div 2; | left = left div 2; | ||
− | + | '''if''' right mod 2 == 1 | |
− | '''if''' right mod 2 == 1 | ||
result = result <tex> \circ </tex> data[right]; | result = result <tex> \circ </tex> data[right]; | ||
right = (right - 2) div 2; | right = (right - 2) div 2; | ||
− | '''if''' left == right | + | '''if''' left == right |
− | result = result <tex> \circ </tex> data[left]; | + | result = result <tex> \circ </tex> data[left]; |
'''return''' result; | '''return''' result; | ||
Версия 10:29, 10 июня 2012
Алгоритм
Реализация запроса снизу вверх в дереве отрезков является, в отличие от реализации запроса сверху вниз, итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее a b.
Построим дерево отрезков и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:
1. Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей(является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от вклада ненужного нам поддерева. 2. Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1), пока границы не пересекутся. 3. Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.
Псевдокод
Пусть результат считаем на отрезке [left, right]. При этом значения передающиеся в функцию left и right должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья).
query(left, right) result = neutral; while left < right if left mod 2 == 0 result = resultdata[left]; left = left div 2; if right mod 2 == 1 result = result data[right]; right = (right - 2) div 2; if left == right result = result data[left]; return result;