<?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=178.66.1.59&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=178.66.1.59&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/178.66.1.59"/>
		<updated>2026-06-03T18:09:28Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_LCA_%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B5_RMQ&amp;diff=20817</id>
		<title>Сведение задачи LCA к задаче RMQ</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_LCA_%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B5_RMQ&amp;diff=20817"/>
				<updated>2012-04-16T16:43:48Z</updated>
		
		<summary type="html">&lt;p&gt;178.66.1.59: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Постановка задачи LCA ==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = '''Наименьшим общим предком (least common ancestor)''' двух узлов &amp;lt;tex&amp;gt;u, v&amp;lt;/tex&amp;gt; в корневом дереве &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; называется узел &amp;lt;tex&amp;gt;w,&amp;lt;/tex&amp;gt; который среди всех узлов, являющихся предками как узла &amp;lt;tex&amp;gt;u,&amp;lt;/tex&amp;gt; так и &amp;lt;tex&amp;gt;v,&amp;lt;/tex&amp;gt; имеет наибольшую глубину.&lt;br /&gt;
}}&lt;br /&gt;
Пусть дано корневое дерево &amp;lt;tex&amp;gt;T.&amp;lt;/tex&amp;gt; На вход подаются запросы вида &amp;lt;tex&amp;gt;(u,\;v),&amp;lt;/tex&amp;gt; для каждого запроса требуется найти их наименьшего общего предка.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Препроцессинг ===&lt;br /&gt;
1) В каждом узле будет храниться глубина узла в корневом дереве &amp;lt;tex&amp;gt;T.&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;depth(u)= \begin{cases}&lt;br /&gt;
0 &amp;amp; u = root(T),\\&lt;br /&gt;
depth(v) + 1 &amp;amp; u = son(v).&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2) Запустим [[Обход в глубину, цвета вершин|обход в глубину]] из корня, который будет строить список посещений узлов. Глубина текущей вершины добавляется в список при входе в эту вершину, а также после каждого возвращения из её сына.&lt;br /&gt;
&lt;br /&gt;
=== Запрос ===&lt;br /&gt;
Обозначим &amp;lt;tex&amp;gt;I[u]&amp;lt;/tex&amp;gt; {{---}} функция, возвращающая любой индекс ячейки в списке глубин &amp;lt;tex&amp;gt;depth&amp;lt;/tex&amp;gt;, в котором хранится глубина узла &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. Ее можно строить во время обхода в глубину.&lt;br /&gt;
Пусть имеется запрос пара узлов &amp;lt;tex&amp;gt;u, v.&amp;lt;/tex&amp;gt; В результате обхода в глубину получился список глубин вершин, в котором наименьшему общему предку вершин &amp;lt;tex&amp;gt;u, v&amp;lt;/tex&amp;gt; соответствует минимальная глубина на отрезке &amp;lt;tex&amp;gt;depth[I[u], I[v]].&amp;lt;/tex&amp;gt; Можно брать любое значение &amp;lt;tex&amp;gt;I[u].&amp;lt;/tex&amp;gt; Для определённости &amp;lt;tex&amp;gt;I[u] \le I[v].&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Доказательство корректности алгоритма ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Приведенный выше алгоритм работает верно.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим два узла &amp;lt;tex&amp;gt;u, v&amp;lt;/tex&amp;gt; корневого дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Для определенности считаем, что &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; является первой при поиске в глубину. На отрезке &amp;lt;tex&amp;gt;depth[I[u]..end]&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;end&amp;lt;/tex&amp;gt; {{---}} последний элемент в &amp;lt;tex&amp;gt;depth&amp;lt;/tex&amp;gt;) хранятся узлы посещенные после &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и, быть может, некоторые вершины из поддерева с корнем &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;(которые имеют глубину больше глубины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;). Аналогично на &amp;lt;tex&amp;gt;depth[1..I[v]]&amp;lt;/tex&amp;gt; {{---}} вершины, посещенные до &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и некоторые вершины из поддерева &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Рассмотрим теперь отрезок &amp;lt;tex&amp;gt;depth[I[u]..I[v]]&amp;lt;/tex&amp;gt;. Поскольку этот отрезок {{---}} путь из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, он проходит через их наименьшего общего предка &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;(в дереве есть только один простой путь между вершинами). Покажем, что его глубина минимальна на отрезке &amp;lt;tex&amp;gt;depth[I[u]..I[v]]&amp;lt;/tex&amp;gt;. Допустим обратное. Все потомки &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; имеют глубину больше. Но тогда получим, что поиск в глубину вышел из поддерева вершины &amp;lt;tex&amp;gt;w&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;
== Пример ==&lt;br /&gt;
Рассмотрим дерево на рисунке 1. Найдем наименьшего общего предка вершин, помеченных красным цветом.&lt;br /&gt;
Список глубин, получающийся в результате обхода в глубину - &amp;lt;tex&amp;gt;[0, 1, 2, 1, 2, 1, 0, 1, 0].&amp;lt;/tex&amp;gt;&lt;br /&gt;
Глубина наименьшего общего предка красных вершин равна минимуму на отрезке &amp;lt;tex&amp;gt;[2, 1, 0, 1].&amp;lt;/tex&amp;gt;&lt;br /&gt;
[[Файл:Lca to rmq.png|thumb|left|рис. 1]]&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Сложность ==&lt;br /&gt;
&lt;br /&gt;
Для нахождения минимального элемента на отрезке можно использовать [[Дерево отрезков. Построение|дерево отрезков]]. Длина массива глубин будет равна &amp;lt;tex&amp;gt;(2n - 1),&amp;lt;/tex&amp;gt; т.е. дерево отрезков будет построено за &amp;lt;tex&amp;gt;O(n).&amp;lt;/tex&amp;gt; Таким образом, препроцессинг работает за &amp;lt;tex&amp;gt;O(n).&amp;lt;/tex&amp;gt; Время выполнения запроса равно времени запроса минимального элемента на отрезке в дереве отрезков, т.е. &amp;lt;tex&amp;gt;O(\log n).&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См.также ==&lt;br /&gt;
*[[Метод двоичного подъема]]&lt;br /&gt;
*[[Решение RMQ с помощью разреженной таблицы]]&lt;br /&gt;
*[[Алгоритм Фарака-Колтона и Бендера]]&lt;br /&gt;
*[[Сведение задачи RMQ к задаче LCA]]&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
*[http://e-maxx.ru/algo/lca Наименьший общий предок. Нахождение за O (sqrt (N)) и O (log N) с препроцессингом O (N)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о наименьшем общем предке]]&lt;/div&gt;</summary>
		<author><name>178.66.1.59</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_LCA_%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B5_RMQ&amp;diff=20813</id>
		<title>Сведение задачи LCA к задаче RMQ</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8_LCA_%D0%BA_%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B5_RMQ&amp;diff=20813"/>
				<updated>2012-04-16T16:33:08Z</updated>
		
		<summary type="html">&lt;p&gt;178.66.1.59: /* Доказательство корректности алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Постановка задачи LCA ==&lt;br /&gt;
{{Определение &lt;br /&gt;
|definition = '''Наименьшим общим предком (least common ancestor)''' двух узлов &amp;lt;tex&amp;gt;u, v&amp;lt;/tex&amp;gt; в корневом дереве &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; называется узел &amp;lt;tex&amp;gt;w,&amp;lt;/tex&amp;gt; который среди всех узлов, являющихся предками как узла &amp;lt;tex&amp;gt;u,&amp;lt;/tex&amp;gt; так и &amp;lt;tex&amp;gt;v,&amp;lt;/tex&amp;gt; имеет наибольшую глубину.&lt;br /&gt;
}}&lt;br /&gt;
Пусть дано корневое дерево &amp;lt;tex&amp;gt;T.&amp;lt;/tex&amp;gt; На вход подаются запросы вида &amp;lt;tex&amp;gt;(u,\;v),&amp;lt;/tex&amp;gt; для каждого запроса требуется найти их наименьшего общего предка.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
=== Препроцессинг ===&lt;br /&gt;
1) В каждом узле будет храниться глубина узла в корневом дереве &amp;lt;tex&amp;gt;T.&amp;lt;/tex&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;depth(u)= \begin{cases}&lt;br /&gt;
0 &amp;amp; u = root(T),\\&lt;br /&gt;
depth(v) + 1 &amp;amp; u = son(v).&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2) Запустим [[Обход в глубину, цвета вершин|обход в глубину]] из корня, который будет строить список посещений узлов. Глубина текущей вершины добавляется в список при входе в эту вершину, а также после каждого возвращения из её сына.&lt;br /&gt;
&lt;br /&gt;
=== Запрос ===&lt;br /&gt;
Обозначим &amp;lt;tex&amp;gt;I[u]&amp;lt;/tex&amp;gt; {{---}} функция, возвращающая все индексы ячеек в списке глубин &amp;lt;tex&amp;gt;depth[start..end]&amp;lt;/tex&amp;gt;, в которых хранится глубина узла &amp;lt;tex&amp;gt;u.&amp;lt;/tex&amp;gt;&lt;br /&gt;
Пусть имеется запрос пара узлов &amp;lt;tex&amp;gt;u, v.&amp;lt;/tex&amp;gt; В результате обхода в глубину получился список глубин вершин, в котором наименьшему общему предку вершин &amp;lt;tex&amp;gt;u, v&amp;lt;/tex&amp;gt; соответствует минимальная глубина на отрезке &amp;lt;tex&amp;gt;depth[I[u], I[v]].&amp;lt;/tex&amp;gt; Можно брать любое значение &amp;lt;tex&amp;gt;I[u].&amp;lt;/tex&amp;gt; Для определённости &amp;lt;tex&amp;gt;I[u] \le I[v].&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Доказательство корректности алгоритма ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Приведенный выше алгоритм работает верно.&lt;br /&gt;
|proof=&lt;br /&gt;
Рассмотрим два узла &amp;lt;tex&amp;gt;u, v&amp;lt;/tex&amp;gt; корневого дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Для определенности считаем, что &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; является первой при поиске в глубину. Обозначим &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} любой индекс из &amp;lt;tex&amp;gt;I[u]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}} из &amp;lt;tex&amp;gt;I[v]&amp;lt;/tex&amp;gt;. На отрезке &amp;lt;tex&amp;gt;depth[a..end]&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;end&amp;lt;/tex&amp;gt; {{---}} последний элемент в &amp;lt;tex&amp;gt;depth&amp;lt;/tex&amp;gt;) хранятся узлы посещенные после &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; и, быть может, некоторые вершины из поддерева с корнем &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;(которые имеют глубину больше глубины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;). Аналогично на &amp;lt;tex&amp;gt;depth[1..b]&amp;lt;/tex&amp;gt; {{---}} вершины, посещенные до &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; и некоторые вершины из поддерева &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Рассмотрим теперь отрезок &amp;lt;tex&amp;gt;depth[a..b]&amp;lt;/tex&amp;gt;. Поскольку этот отрезок {{---}} путь из &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, он проходит через их наименьшего общего предка &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;(в дереве есть только один простой путь между вершинами). Покажем, что его глубина минимальна на отрезке &amp;lt;tex&amp;gt;depth[a..b]&amp;lt;/tex&amp;gt;. Допустим обратное. Все потомки &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; имеют глубину больше. Но тогда получим, что поиск в глубину вышел из поддерева вершины &amp;lt;tex&amp;gt;w&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;
== Пример ==&lt;br /&gt;
Рассмотрим дерево на рисунке 1. Найдем наименьшего общего предка вершин, помеченных красным цветом.&lt;br /&gt;
Список глубин, получающийся в результате обхода в глубину - &amp;lt;tex&amp;gt;[0, 1, 2, 1, 2, 1, 0, 1, 0].&amp;lt;/tex&amp;gt;&lt;br /&gt;
Глубина наименьшего общего предка красных вершин равна минимуму на отрезке &amp;lt;tex&amp;gt;[2, 1, 0, 1].&amp;lt;/tex&amp;gt;&lt;br /&gt;
[[Файл:Lca to rmq.png|thumb|left|рис. 1]]&lt;br /&gt;
&amp;lt;div style='clear:left;'&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Сложность ==&lt;br /&gt;
&lt;br /&gt;
Для нахождения минимального элемента на отрезке можно использовать [[Дерево отрезков. Построение|дерево отрезков]]. Длина массива глубин будет равна &amp;lt;tex&amp;gt;(2n - 1),&amp;lt;/tex&amp;gt; т.е. дерево отрезков будет построено за &amp;lt;tex&amp;gt;O(n).&amp;lt;/tex&amp;gt; Таким образом, препроцессинг работает за &amp;lt;tex&amp;gt;O(n).&amp;lt;/tex&amp;gt; Время выполнения запроса равно времени запроса минимального элемента на отрезке в дереве отрезков, т.е. &amp;lt;tex&amp;gt;O(\log n).&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== См.также ==&lt;br /&gt;
*[[Метод двоичного подъема]]&lt;br /&gt;
*[[Решение RMQ с помощью разреженной таблицы]]&lt;br /&gt;
*[[Алгоритм Фарака-Колтона и Бендера]]&lt;br /&gt;
*[[Сведение задачи RMQ к задаче LCA]]&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
*[http://e-maxx.ru/algo/lca Наименьший общий предок. Нахождение за O (sqrt (N)) и O (log N) с препроцессингом O (N)]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о наименьшем общем предке]]&lt;/div&gt;</summary>
		<author><name>178.66.1.59</name></author>	</entry>

	</feed>