Реализация запроса в дереве отрезков снизу — различия между версиями
| Martoon (обсуждение | вклад) м (Картинка) | Martoon (обсуждение | вклад)  м (→Псевдокод) | ||
| Строка 78: | Строка 78: | ||
|     query(left, right) |     query(left, right) | ||
| − |        left_res = neutral; | + |        left_res = '''neutral'''; | 
| − |        right_res = neutral; | + |        right_res = '''neutral'''; | 
|        '''while''' left < right |        '''while''' left < right | ||
|           '''if''' left mod 2 == 0 |           '''if''' left mod 2 == 0 | ||
Версия 00:28, 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_res  data[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;


