Реализация запроса в дереве отрезков сверху

Материал из Викиконспекты
Перейти к: навигация, поиск

Алгоритм

Будем рассматривать запрос на примере задачи RSQ(запрос суммы)

Пример дерева отрезков для вычисления сумм

Пусть есть дерево отрезков и задача найти сумму на отрезке [math][a .. b][/math], далее искомый.

Запустим рекурсивную процедуру от всего отрезка.

Проверять будем два условия :

  • если текущий отрезок не пересекается с искомым, то возвращаем нулевое значение.

Например:

текущий [math][1..2][/math], а искомый [math][3 .. 4][/math];

  • текущий отрезок целиком внутри, то возвращаем значение в вершине.

Например:

текущий [math][2..3][/math], а искомый [math][1 .. 4][/math];

Далее переходим к рекурсивным вызовам результат функции от текущего отрезка и искомого = сумма результатов от детей текущего отрезка и искомого.

Пример

Дерево отрезков

Рассмотрим работу программы на дереве отрезков для элементов [math][1 .. 8][/math]. Пусть запрашиваемая сумма - это отрезок [math][2 .. 5][/math].

  • Текущий отрезок [math][1 .. 8][/math], он больше [math][2 .. 5][/math] => переходим по рекурсивным вызовам на [math][1 .. 4][/math] и [math][5 .. 8][/math]


  • [math][1 .. 4][/math] выходит за границы[math] [2 .. 5][/math], [math][5 .. 8][/math] выходит за границы [math][2 .. 5][/math] => переходим по рекурсивным вызовам на [math][1 .. 2][/math], [math][3 .. 4][/math] и [math][5 .. 6][/math], [math][7 .. 8][/math].


  • [math][1 .. 2][/math] выходит за границы [math][2 .. 5][/math] => переходим в листья 1, 2; [math][3 .. 4][/math] целиком внутри [math][2 .. 5][/math] => возвращаем значение в [math][3 .. 4][/math];

[math][7 .. 8][/math] не пересекается с [math][2 .. 5][/math] => возвращаем нулевое значение, [math][5 .. 6][/math] выходит за границы [math][2 .. 5][/math] => переходим к листьям 5 и 6


  • лист 6 не пересекается с отрезком [math][2 .. 5][/math] => возвращаем нулевое значение, лист 5 целиков внутри [math][2 .. 5][/math] => возвращаем значение в листе 5.

Реализация

 int sum (int v, int tl, int tr, int l, int r)
 {
       if ([l,r] [math]\bigcap[/math] [tl, tr]) = 
           return 0;
       if ([l,r] [math]\subset[/math] [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);
 } 

Ссылки

- MAXimal :: algo :: Дерево отрезков

- Дерево отрезков — Википедия