<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=91.108.28.12&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=91.108.28.12&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/91.108.28.12"/>
		<updated>2026-05-22T11:50:32Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Level_Ancestor_problem&amp;diff=71216</id>
		<title>Level Ancestor problem</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Level_Ancestor_problem&amp;diff=71216"/>
				<updated>2019-05-14T17:04:18Z</updated>
		
		<summary type="html">&lt;p&gt;91.108.28.12: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Задача о уровне предка''' (англ. &amp;quot;Level Ancestor problem&amp;quot;) является задачей о превращении данного корневого подвешенного дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; в структуру данных, которая сможет определить предка любого узла на заданном расстоянии от корня дерева.&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Дано подвешенное корневое дерево &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; c &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами. Поступают запросы вида &amp;lt;tex&amp;gt;LA(v, k)&amp;lt;/tex&amp;gt;, для каждого из которых необходимо&lt;br /&gt;
найти предка вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, который находится на расстоянии &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; от корня дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
== Наивная реализация и двоичные подъемы ==&lt;br /&gt;
[[Файл:LevelAncestor.png|200px|thumb|right]]&lt;br /&gt;
Используя обход в глубину посчитаем глубину каждой вершины дерева (это можно сделать за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;), после чего можем из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; подняться до необходимой глубины вершины &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;,&lt;br /&gt;
что так же в худшем случае работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили алгоритм за &amp;lt; &amp;lt;tex&amp;gt;O(n), O(n)&amp;lt;/tex&amp;gt; &amp;gt;, где время ответа на&lt;br /&gt;
запрос можно улучшить до &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; c помощью [[Метод двоичного подъёма | предподсчета двоичных подъемов]]  ,&lt;br /&gt;
но тогда и время предподсчета в наивной реализации (посчитать подъемы для всех вершин) ухудшится до &amp;lt; &amp;lt;tex&amp;gt;O(n \log n),&lt;br /&gt;
O(\log n)&amp;lt;/tex&amp;gt; &amp;gt;. Альтернативой данным двум алгоритмам является полный предподсчет всех возможных запросов, что соответственно дает нам асимптотику &amp;lt; &amp;lt;tex&amp;gt;O(n^2), O(1)&amp;lt;/tex&amp;gt; &amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В данном примере поступает запрос &amp;lt;tex&amp;gt;LA(v, 2)&amp;lt;/tex&amp;gt;, на который алгоритм должен дать ответ &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Использование Heavy-light декомпозиции ==&lt;br /&gt;
Этот алгоритм базируется на различных способах [[Heavy-light декомпозиция | декомпозиции дерева]] (выберем heavy-light декомпозицию), из свойств этого разбиения следует,&lt;br /&gt;
что подняться на любую высоту из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; мы можем за время &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Данное разбиение можно строить за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает нам алгоритм за &amp;lt; &amp;lt;tex&amp;gt;O(n), O(\log n)&amp;lt;/tex&amp;gt; &amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм лестниц ==&lt;br /&gt;
=== Longest path decomposition ===&lt;br /&gt;
Разобьем все вершины на пути следующим образом. Обойдем дерево с помощью обхода в глубину, пусть мы стоим в вершине&lt;br /&gt;
&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, обойдем всех ее детей, добавив &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в путь, идущий в самое глубокое поддерево,&lt;br /&gt;
т.е. в котором находится вершина с самой большой глубиной.&lt;br /&gt;
Для каждой вершины сохраним номер пути в который она входит.&lt;br /&gt;
=== Ladder decomposition ===&lt;br /&gt;
Увеличим каждый путь в два раза вверх, для каждого нового пути сохраним все входящие в него вершины,&lt;br /&gt;
а для каждой вершины сохраним ее номер в пути, в который она входит. Построение обычной longest-path декомпозиции займет у&lt;br /&gt;
нас &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени (обход в глубину), соответственно удлиннение каждого пути ухудшит асимптотику до  &amp;lt;tex&amp;gt;O(n \log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
После этого посчитаем двоичные подъемы для каждой вершины за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;, что соответственно не ухудшит асимптотику.&lt;br /&gt;
&lt;br /&gt;
Пусть после этого нам пришел запрос &amp;lt;tex&amp;gt;LA(v, k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Сделаем один максимально большой прыжок вверх с помощью насчитанных двоичных подъемов.&lt;br /&gt;
#&amp;lt;tex&amp;gt;i = \log k&amp;lt;/tex&amp;gt;&lt;br /&gt;
#&amp;lt;tex&amp;gt;v = p_i[v]&amp;lt;/tex&amp;gt;&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
Рассмотрим путь, на котором лежит вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; до удвоения. Он длины хотя бы &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt;, так как мы точно знаем, что существует вершина потомок &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, расстояние до которого ровно &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt; (это вершина, из которой мы только что пришли). Значит, после удвоения этот путь стал длины хотя бы &amp;lt;tex&amp;gt;2^{i + 1}&amp;lt;/tex&amp;gt;, причем хотя бы &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt; вершин в нем - предки &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Это означает, что вершина, которую мы ищем, находится на этом пути (иначе бы мы могли до этого прыгнуть еще на &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt; вверх). Так как мы знаем позицию &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в этом пути, то нужную вершину мы можем найти за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, наш алгоритм работает за &amp;lt; &amp;lt;tex&amp;gt;O(n\log n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;. Методом четырех русских данный метод можно улучшить до &amp;lt; &amp;lt;tex&amp;gt;O(n), O(1)&amp;lt;/tex&amp;gt; &amp;gt; с помощью оптимизации предподсчета.&lt;br /&gt;
==  The Macro-Micro-Tree Algorithm ==&lt;br /&gt;
В данном разделе мы докажем, что предподсчет предыдущего алгоритма можно улучшить до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Для начала рассмотрим алгоритм &amp;lt; &amp;lt;tex&amp;gt;O(L\log n + n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;, где &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; это количество листьев.&lt;br /&gt;
*С помощью обхода в глубину запомним по одному листу в ее поддереве для каждой вершины&lt;br /&gt;
*Воспользуемся алгоритмом лестниц, но будем выполнять предподсчет только для листьев.&lt;br /&gt;
Рассмотрим как можно улучшить данный алгоритм:&lt;br /&gt;
*Зададим некую функцию &amp;lt;tex&amp;gt;S(n) = \dfrac{1}{4} \log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Посчитаем размер поддерева для каждой вершины с помощью обхода в глубину, после чего удалим все вершины размер поддерева которых меньше чем  &amp;lt;tex&amp;gt;S(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Забудем на время про удаленные поддеревья, для оставшегося дерева наш алгоритм работает за &amp;lt; &amp;lt;tex&amp;gt;O(\dfrac{n}{S(n)} \log n + n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;. Получаем алгоритм &amp;lt; &amp;lt;tex&amp;gt;O(n), O(1) &amp;lt;/tex&amp;gt; &amp;gt;. Для удаленных поддеревьев же выполним полный предподсчет: таких деревьев не более чем &amp;lt;tex&amp;gt;2^{2S(n)}&amp;lt;/tex&amp;gt;, что дает асимптотику предподсчета &amp;lt;tex&amp;gt;O(\sqrt{n} \log^2{n}) = o(n) = O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге полученный алгоритм действительно работает за &amp;lt; &amp;lt;tex&amp;gt;O(n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*https://www.cadmo.ethz.ch/education/lectures/HS18/SAADS/reports/5.pdf&lt;br /&gt;
*https://en.wikipedia.org/wiki/Level_ancestor_problem&lt;/div&gt;</summary>
		<author><name>91.108.28.12</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=Level_Ancestor_problem&amp;diff=71215</id>
		<title>Level Ancestor problem</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=Level_Ancestor_problem&amp;diff=71215"/>
				<updated>2019-05-14T17:03:34Z</updated>
		
		<summary type="html">&lt;p&gt;91.108.28.12: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Задача о уровне предка''' (англ. &amp;quot;Level Ancestor problem&amp;quot;) является задачей о превращении данного корневого подвешенного дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; в структуру данных, которая сможет определить предка любого узла на заданном расстоянии от корня дерева.&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition = Дано подвешенное корневое дерево &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; c &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вершинами. Поступают запросы вида &amp;lt;tex&amp;gt;LA(v, k)&amp;lt;/tex&amp;gt;, для каждого из которых необходимо&lt;br /&gt;
найти предка вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, который находится на расстоянии &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; от корня дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
== Наивная реализация и двоичные подъемы ==&lt;br /&gt;
[[Файл:LevelAncestor.png|200px|thumb|right]]&lt;br /&gt;
Используя обход в глубину посчитаем глубину каждой вершины дерева (это можно сделать за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;), после чего можем из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; подняться до необходимой глубины вершины &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;,&lt;br /&gt;
что так же в худшем случае работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Получили алгоритм за &amp;lt; &amp;lt;tex&amp;gt;O(n), O(n)&amp;lt;/tex&amp;gt; &amp;gt;, где время ответа на&lt;br /&gt;
запрос можно улучшить до &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; c помощью [[Метод двоичного подъёма | предподсчета двоичных подъемов]]  ,&lt;br /&gt;
но тогда и время предподсчета в наивной реализации (посчитать подъемы для всех вершин) ухудшится до &amp;lt; &amp;lt;tex&amp;gt;O(n \log n),&lt;br /&gt;
O(\log n)&amp;lt;/tex&amp;gt; &amp;gt;. Альтернативой данным двум алгоритмам является полный предподсчет всех возможных запросов, что соответственно дает нам асимптотику &amp;lt; &amp;lt;tex&amp;gt;O(n^2), O(1)&amp;lt;/tex&amp;gt; &amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В данном примере поступает запрос &amp;lt;tex&amp;gt;LA(v, 2)&amp;lt;/tex&amp;gt;, на который алгоритм должен дать ответ &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Использование Heavy-light декомпозиции ==&lt;br /&gt;
Этот алгоритм базируется на различных способах [[Heavy-light декомпозиция | декомпозиции дерева]] (выберем heavy-light декомпозицию), из свойств этого разбиения следует,&lt;br /&gt;
что подняться на любую высоту из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; мы можем за время &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Данное разбиение можно строить за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;, что дает нам алгоритм за &amp;lt; &amp;lt;tex&amp;gt;O(n), O(\log n)&amp;lt;/tex&amp;gt; &amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм лестниц ==&lt;br /&gt;
=== Longest path decomposition ===&lt;br /&gt;
Разобьем все вершины на пути следующим образом. Обойдем дерево с помощью обхода в глубину, пусть мы стоим в вершине&lt;br /&gt;
&amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, обойдем всех ее детей, добавив &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в путь, идущий в самое глубокое поддерево,&lt;br /&gt;
т.е. в котором находится вершина с самой большой глубиной.&lt;br /&gt;
Для каждой вершины сохраним номер пути в который она входит.&lt;br /&gt;
=== Ladder decomposition ===&lt;br /&gt;
Увеличим каждый путь в два раза вверх, для каждого нового пути сохраним все входящие в него вершины,&lt;br /&gt;
а для каждой вершины сохраним ее номер в пути, в который она входит. Построение обычной longest-path декомпозиции займет у&lt;br /&gt;
нас &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени (обход в глубину), соответственно удлиннение каждого пути ухудшит асимптотику до  &amp;lt;tex&amp;gt;O(n \log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Двоичные подъемы ===&lt;br /&gt;
После этого посчитаем двоичные подъемы для каждой вершины за &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;, что соответственно не ухудшит асимптотику.&lt;br /&gt;
&lt;br /&gt;
Пусть после этого нам пришел запрос &amp;lt;tex&amp;gt;LA(v, k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Сделаем один максимально большой прыжок вверх с помощью насчитанных двоичных подъемов.&lt;br /&gt;
#&amp;lt;tex&amp;gt;i = \log k&amp;lt;/tex&amp;gt;&lt;br /&gt;
#&amp;lt;tex&amp;gt;v = p_i[v]&amp;lt;/tex&amp;gt;&lt;br /&gt;
=== Доказательство корректности ===&lt;br /&gt;
* Рассмотрим путь, на котором лежит вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; до удвоения. Он длины хотя бы &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt;, так как мы точно знаем, что существует вершина потомок &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, расстояние до которого ровно &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt; (это вершина, из которой мы только что пришли). Значит, после удвоения этот путь стал длины хотя бы &amp;lt;tex&amp;gt;2^{i + 1}&amp;lt;/tex&amp;gt;, причем хотя бы &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt; вершин в нем - предки &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Это означает, что вершина, которую мы ищем, находится на этом пути (иначе бы мы могли до этого прыгнуть еще на &amp;lt;tex&amp;gt;2^i&amp;lt;/tex&amp;gt; вверх). Так как мы знаем позицию &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в этом пути, то нужную вершину мы можем найти за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, наш алгоритм работает за &amp;lt; &amp;lt;tex&amp;gt;O(n\log n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;. Методом четырех русских данный метод можно улучшить до &amp;lt; &amp;lt;tex&amp;gt;O(n), O(1)&amp;lt;/tex&amp;gt; &amp;gt; с помощью оптимизации предподсчета.&lt;br /&gt;
==  The Macro-Micro-Tree Algorithm ==&lt;br /&gt;
В данном разделе мы докажем, что предподсчет предыдущего алгоритма можно улучшить до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Для начала рассмотрим алгоритм &amp;lt; &amp;lt;tex&amp;gt;O(L\log n + n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;, где &amp;lt;tex&amp;gt;L&amp;lt;/tex&amp;gt; это количество листьев.&lt;br /&gt;
*С помощью обхода в глубину запомним по одному листу в ее поддереве для каждой вершины&lt;br /&gt;
*Воспользуемся алгоритмом лестниц, но будем выполнять предподсчет только для листьев.&lt;br /&gt;
Рассмотрим как можно улучшить данный алгоритм:&lt;br /&gt;
*Зададим некую функцию &amp;lt;tex&amp;gt;S(n) = \dfrac{1}{4} \log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
*Посчитаем размер поддерева для каждой вершины с помощью обхода в глубину, после чего удалим все вершины размер поддерева которых меньше чем  &amp;lt;tex&amp;gt;S(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
*Забудем на время про удаленные поддеревья, для оставшегося дерева наш алгоритм работает за &amp;lt; &amp;lt;tex&amp;gt;O(\dfrac{n}{S(n)} \log n + n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;. Получаем алгоритм &amp;lt; &amp;lt;tex&amp;gt;O(n), O(1) &amp;lt;/tex&amp;gt; &amp;gt;. Для удаленных поддеревьев же выполним полный предподсчет: таких деревьев не более чем &amp;lt;tex&amp;gt;2^{2S(n)}&amp;lt;/tex&amp;gt;, что дает асимптотику предподсчета &amp;lt;tex&amp;gt;O(\sqrt{n} \log^2{n}) = o(n) = O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге полученный алгоритм действительно работает за &amp;lt; &amp;lt;tex&amp;gt;O(n), O(1)&amp;lt;/tex&amp;gt; &amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*https://www.cadmo.ethz.ch/education/lectures/HS18/SAADS/reports/5.pdf&lt;br /&gt;
*https://en.wikipedia.org/wiki/Level_ancestor_problem&lt;/div&gt;</summary>
		<author><name>91.108.28.12</name></author>	</entry>

	</feed>