Level Ancestor problem — различия между версиями
Romech (обсуждение | вклад) |
|||
Строка 1: | Строка 1: | ||
− | '''Задача о уровне предка''' (англ. "Level Ancestor problem") является задачей о превращении данного корневого дерева T в структуру данных, которая сможет определить предка любого узла на заданном расстоянии от корня дерева. | + | [[Файл:LevelAncestor.png|120px|thumb|right]]'''Задача о уровне предка''' (англ. "Level Ancestor problem") является задачей о превращении данного корневого дерева T в структуру данных, которая сможет определить предка любого узла на заданном расстоянии от корня дерева. |
+ | В данном примере поступает запрос <tex>LA(v, 2)</tex>, на который алгоритм должен дать ответ h. | ||
{{Задача | {{Задача | ||
− | |definition = Дано корневое дерево <tex>T</tex> c <tex>n</tex> вершинами. Поступают запросы вида <tex>(v, k)</tex>, для каждого из которых необходимо найти предка вершины <tex>v</tex>, который находится на расстоянии <tex>k</tex> от корня дерева <tex>T</tex>. | + | |definition = Дано корневое дерево <tex>T</tex> c <tex>n</tex> вершинами. Поступают запросы вида <tex>LA(v, k)</tex>, для каждого из которых необходимо найти предка вершины <tex>v</tex>, который находится на расстоянии <tex>k</tex> от корня дерева <tex>T</tex>. |
}} | }} | ||
− | == Наивная реализация == | + | == Наивная реализация и двоичные подъемы == |
− | Используя обход в глубину посчитаем глубину каждой вершины дерева (это можно сделать за <tex>O(n)</tex>), после чего можем из вершины <tex>v</tex> подняться до необходимой глубины вершины <tex>k</tex>, что так же в худшем случае работает за <tex>O(n)</tex>. Получили алгоритм за <tex><O(n),O(n)></tex>, где время ответа на запрос можно улучшить до <tex>O(\log n)</tex> c помощью [[Метод двоичного подъёма | предподсчета двоичных подъемов]], но тогда и время предподсчета в наивной реализации (посчитать подъемы для всех вершин) ухудшится до <tex><O(n \log n),O(\log n)></tex>. | + | [[Файл:Двоичные_подъемы.png|150px|thumb|right|Двоичные подъемы]] |
− | == | + | Используя обход в глубину посчитаем глубину каждой вершины дерева (это можно сделать за <tex>O(n)</tex>), после чего можем из вершины <tex>v</tex> подняться до необходимой глубины вершины <tex>k</tex>, что так же в худшем случае работает за <tex>O(n)</tex>. Получили алгоритм за <tex><O(n),O(n)></tex>, где время ответа на запрос можно улучшить до <tex>O(\log n)</tex> c помощью [[Метод двоичного подъёма | предподсчета двоичных подъемов]] , но тогда и время предподсчета в наивной реализации (посчитать подъемы для всех вершин) ухудшится до <tex><O(n \log n),O(\log n)></tex>. |
+ | == Использование Heavy-light декомпозиции == | ||
+ | [[Файл:Heavylight.png|150px|thumb|right|Heavy-light декомпозиция]] | ||
Этот алгоритм базируется на различных способах [[Heavy-light декомпозиция | декомпозиции дерева]] (выберем heavy-light декомпозицию), из свойств этого разбиения следует, что подняться на любую высоту из вершины <tex>v</tex> мы можем за <tex>O(\log n)</tex>. Данное разбиение можно строить за <tex>O(n)</tex>, что дает нам алгоритм за <tex><O(n), O(\log n)></tex>. | Этот алгоритм базируется на различных способах [[Heavy-light декомпозиция | декомпозиции дерева]] (выберем heavy-light декомпозицию), из свойств этого разбиения следует, что подняться на любую высоту из вершины <tex>v</tex> мы можем за <tex>O(\log n)</tex>. Данное разбиение можно строить за <tex>O(n)</tex>, что дает нам алгоритм за <tex><O(n), O(\log n)></tex>. | ||
− | == Алгоритм | + | == Алгоритм лестниц == |
Версия 23:36, 6 мая 2019
Задача о уровне предка (англ. "Level Ancestor problem") является задачей о превращении данного корневого дерева T в структуру данных, которая сможет определить предка любого узла на заданном расстоянии от корня дерева.
В данном примере поступает запрос
, на который алгоритм должен дать ответ h.Задача: |
Дано корневое дерево | c вершинами. Поступают запросы вида , для каждого из которых необходимо найти предка вершины , который находится на расстоянии от корня дерева .
Наивная реализация и двоичные подъемы
Используя обход в глубину посчитаем глубину каждой вершины дерева (это можно сделать за предподсчета двоичных подъемов , но тогда и время предподсчета в наивной реализации (посчитать подъемы для всех вершин) ухудшится до .
), после чего можем из вершины подняться до необходимой глубины вершины , что так же в худшем случае работает за . Получили алгоритм за , где время ответа на запрос можно улучшить до c помощьюИспользование Heavy-light декомпозиции
Этот алгоритм базируется на различных способах декомпозиции дерева (выберем heavy-light декомпозицию), из свойств этого разбиения следует, что подняться на любую высоту из вершины мы можем за . Данное разбиение можно строить за , что дает нам алгоритм за .