Изменения

Перейти к: навигация, поиск

Сжатое многомерное дерево отрезков

4432 байта добавлено, 10:00, 7 июня 2011
Нет описания правки
{{Определение
|definition=
Пусть дан <tex>p</tex>-мерный массив и множество <tex>\Omega</tex>, состоящее из <tex>n</tex> его элементов.'''<br>Сжатым <tex>p</tex>-мерным деревом отрезков''' называется модификация <tex>p</tex>-мерного дерева отрезков, позволяющая сократить объем занимаемой им памяти до реализовывать моноидальные операции (нахождение количества элементов, минимального элемента, etc) над элементами множества <tex>O(n\Omega</tex>,log^{находящимися на <tex>p</tex>-1}\мерном прямоугольнике <tex>(x_a,x_b),(y_a,y_b),...,(z_a,nz_b)</tex>.
}}
Например, сжатое дерево отрезков решает следующую задачу: заданы <tex>n</tex> точек на плоскости с координатами <tex>(x_i,y_i)</tex>, посчитать количество точек на прямоугольнике <tex>(x_a,x_b),(y_a,y_b)</tex>.
позволяющая для заданного множества из ==Структура==Вообще говоря, с поставленной задачей справится и обычное <tex>np</tex>-мерное дерево отрезков. Очевидно, запрос операции на <tex> p</tex>-мерных точек мерном прямоугольнике c помощью такой структуры будет выполняться за время <tex>O(log^p\,n)</tex> отвечать на запрос количества точек, находящихся а сама структура будет занимать порядка <tex>\Omega(S)</tex> памяти, где <tex>S</tex> — количество элементов в <tex>p</tex>-мерном прямоугольнике массиве. Однако, можно провести следующую оптимизацию — каждый раз дерево отрезков внутри вершины будем строить только по тем элементам, которые встречаются в отрезке, за который отвечает эта вершина. Действительно, другие элементы уже были "исключены" и заведомо лежат вне желаемого <tex>p</tex>-мерного прямоугольника. Алгоритм построения такого "усеченного" дерева отрезков будет выглядеть следующим образом:<br>* Cоставить массив из всех <tex>n</tex> элементов множества <tex>\Omega</tex>, упорядочить его по первой координате* Построить на нём дерево отрезков (для удобства будем использовать сохранение всего подмассива в каждой вершине дерева отрезков)* Все подмассивы в вершинах получившегося дерева отрезков упорядочить по следующей координате, после чего повторить построение дерева для каждого из них Псевдокод: build_normal_tree(element[] array) { //построение одномерного дерева отрезков на массиве array с сохранением подмассива в каждой вершине } get_inside_array(vertex) { //получение подмассива, сохраненного в вершине vertex } build_compressed_tree(x_1element[] array,x_2int coordinate) { //собственно,...построение сжатого дерева отрезков if (coordinate < p) { sort(array,coordinate); //сортировка массива по нужной координате segment_tree = build_normal_tree(z_1array); for (each vertex in segment_tree) { build_compressed_tree(inside_array(each),z_2coordinate + 1); } } }  При такой оптимизации асимптотика размера структуры составит <tex>O(n\,log^{p-1}\,n)</tex>, а запрос будет аналогичен запросу в обычном <tex>p</tex>-мерном дереве отрезков за <tex>O(log^p\,n)</tex>. Но расплатой станет невозможность делать произвольный запрос модификации: в самом деле, если появится новый элемент, то это приведёт к тому, что мы должны будем в каком-либо дереве отрезков по второй или более координате добавить новый элемент в середину, что эффективно сделать невозможно. Поэтому, если задача поставлена на плоскости, то на практике используются более гибкие структуры данных, например, [[Декартово дерево по неявному ключу]].
Анонимный участник

Навигация