333
правки
Изменения
Нет описания правки
==Алгоритм==
Будем передавать в качестве параметров рекурсий следующие переменные:
* <tex>node</tex> {{---}} номер(в массиве с деревом отрезков) текущей вершины дерева.
* <tex>a</tex>, <tex>b</tex> {{---}} левая и правая границы запрашиваемого отрезка.
Пусть <tex>l</tex>, <tex>r</tex> {{---}} это левая и правая границы отрезков, за которые "отвечает" наша вершина, причем левые границы обоих отрезков - включительно, а правые - нет. В дальнейшем будем называть подобную структуру полуинтвервалом.
Запустим рекурсивную процедуру от всего отрезка(то есть от корневой вершины).
Для текущего состояния проверяем следующие условия :
* Если текущий отрезок полуинтервал не пересекается с искомым, то возвращаем нулевое значение.''Например'': текущий <tex>[1..2]3)</tex>, а искомый <tex>[3 .. 4]5)</tex>;
* Текущий отрезок полуинтервал совпадает, то возвращаем значение в текущей вершине.''Например'': текущий и искомый <tex>[2..3]4)</tex>;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом сумма в зависимости от типа запроса возвращаем значение на текущем отрезке равна сумме результатов функций, запущенных как некоторую функцию от детейрезультатов выполнения на детях.
''Замечание:''
При передаче новых параметров следует изменять не только границы, за которые отвечает текущая вершина, но и границы запрашиваемого отрезкаполуинтервала, чтобы на последующих шагах произошло полное совпадение отрезковполуинтервалов.
Так как каждый отрезок полуинтервал разбивается не более, чем на <tex>O(\log n)</tex> отрезков полуинтервал (поскольку на каждом уровне дерева может быть не более двух отрезков полуинтервалов из разбиения, а всего уровней <tex>\log n</tex> ), то данная реализация выполняется за <tex>O(\log n)</tex>.
*Текущий отрезок полуинтервал <tex>[1 0 .. 8])</tex>, он больше <tex>[2 1 .. 5])</tex> => переходим по рекурсивным вызовам на <tex>[1 0 .. 4])</tex> и <tex>[5 4 .. 8])</tex>
*<tex>[1 0 .. 4])</tex> выходит за границы<tex> [2 1 .. 5])</tex>, <tex>[5 4 .. 8])</tex> выходит за границы <tex>[2 1 .. 5])</tex> => переходим по рекурсивным вызовам на <tex>[1 0 .. 2])</tex>, <tex>[3 2 .. 4])</tex> и <tex>[5 4 .. 6])</tex>, <tex>[7 6 .. 8])</tex>.
*<tex>[1 0 .. 2])</tex> выходит за границы <tex>[2 1 .. 5])</tex> => переходим в листья 0, 1, 2; <tex>[3 2 .. 4])</tex> целиком внутри <tex>[2 1 .. 5])</tex> => возвращаем значение в <tex>[3 2 .. 4])</tex>; <tex>[7 6 .. 8])</tex> не пересекается с <tex>[2 1 .. 5])</tex> => возвращаем нулевое значение, <tex>[5 4 .. 6])</tex> выходит за границы <tex>[2 1 .. 5])</tex> => переходим к листьям <tex>54</tex> и <tex>65</tex>
*лист листья <tex>65</tex> и <tex>0</tex> не пересекается с отрезком полуинтервалом <tex>[2 1 .. 5])</tex> => возвращаем нулевое значение, лист листья <tex>4</tex>5и <tex>1</tex> целиков внутри <tex>[2 1 .. 5])</tex> => возвращаем значение значения в листе <tex>5</tex>этих листьях.
==Реализация==