Level Ancestor problem — различия между версиями
Romech (обсуждение | вклад) |
|||
| Строка 2: | Строка 2: | ||
{{Задача | {{Задача | ||
| − | |definition = Дано корневое дерево <tex>T</tex> c <tex>n</tex> вершинами. Поступают запросы вида <tex>LA(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>. | ||
}} | }} | ||
== Наивная реализация и двоичные подъемы == | == Наивная реализация и двоичные подъемы == | ||
[[Файл:LevelAncestor.png|200px|thumb|right]] | [[Файл:LevelAncestor.png|200px|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> >. Альтернативой данным двум алгоритмам является полный предподсчет всех возможных запросов, что соответственно дает нам ассимптотику < <tex>O(n^2), O(1)</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> >. Альтернативой данным двум алгоритмам является полный предподсчет всех возможных запросов, что соответственно дает нам ассимптотику < <tex>O(n^2), O(1)</tex> >. | ||
В данном примере поступает запрос <tex>LA(v, 2)</tex>, на который алгоритм должен дать ответ h. | В данном примере поступает запрос <tex>LA(v, 2)</tex>, на который алгоритм должен дать ответ h. | ||
== Использование Heavy-light декомпозиции == | == Использование 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> >. | ||
== Алгоритм лестниц == | == Алгоритм лестниц == | ||
| + | =Longest path decomposition= | ||
| + | Разобьем все вершины на пути следующим образом. Обойдем дерево с помощью обхода в глубину, пусть мы стоим в вершине | ||
| + | <tex>v</tex>, обойдем всех ее детей, добавив <tex>v<\tex> в путь, идущий в самое глубокое поддерево, | ||
| + | т.е. в котором находится вершина с саомй большой глубиной. | ||
| + | Для каждой вершины сохраним номер пути в который она входит. | ||
| + | =Ladder decomposition= | ||
| + | Увеличим каждый путь в два раза вверх, для каждого ового пути сохраним все входящие в него вершины, | ||
| + | а для каждой вершины сохраним ее номер в пути, в который она входит. Построение обычной longest-path декомпозиции займет у | ||
| + | нас O(n) времени (обход в глубину), соответственно удлиннение каждого пути ухудшит ассимптотику до <tex>O(n \logn)</tex>. | ||
| + | После этого посчитаем двоичные подьемы для каждой вершины за <tex>O(\log n)</tex>, что соответственно не ухудшит ассимптотику. | ||
| + | |||
| + | Пусть после этого нам пришел запрос <tex>LA(v, k)</tex>. | ||
Версия 22:54, 11 мая 2019
Задача о уровне предка (англ. "Level Ancestor problem") является задачей о превращении данного корневого дерева T в структуру данных, которая сможет определить предка любого узла на заданном расстоянии от корня дерева.
| Задача: |
| Дано корневое дерево c вершинами. Поступают запросы вида , для каждого из которых необходимо найти предка вершины , который находится на расстоянии от корня дерева . |
Содержание
Наивная реализация и двоичные подъемы
Используя обход в глубину посчитаем глубину каждой вершины дерева (это можно сделать за ), после чего можем из вершины подняться до необходимой глубины вершины , что так же в худшем случае работает за . Получили алгоритм за < >, где время ответа на запрос можно улучшить до c помощью предподсчета двоичных подъемов , но тогда и время предподсчета в наивной реализации (посчитать подъемы для всех вершин) ухудшится до < >. Альтернативой данным двум алгоритмам является полный предподсчет всех возможных запросов, что соответственно дает нам ассимптотику < >.
В данном примере поступает запрос , на который алгоритм должен дать ответ h.
Использование Heavy-light декомпозиции
Этот алгоритм базируется на различных способах декомпозиции дерева (выберем heavy-light декомпозицию), из свойств этого разбиения следует, что подняться на любую высоту из вершины мы можем за . Данное разбиение можно строить за , что дает нам алгоритм за < >.
Алгоритм лестниц
Longest path decomposition
Разобьем все вершины на пути следующим образом. Обойдем дерево с помощью обхода в глубину, пусть мы стоим в вершине , обойдем всех ее детей, добавив . После этого посчитаем двоичные подьемы для каждой вершины за , что соответственно не ухудшит ассимптотику.
Пусть после этого нам пришел запрос .