<?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=212.109.7.175&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=212.109.7.175&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/212.109.7.175"/>
		<updated>2026-04-06T12:42:58Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D0%B4%D1%8A%D1%91%D0%BC%D0%B0&amp;diff=72103</id>
		<title>Метод двоичного подъёма</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D0%B4%D1%8A%D1%91%D0%BC%D0%B0&amp;diff=72103"/>
				<updated>2020-01-11T21:27:38Z</updated>
		
		<summary type="html">&lt;p&gt;212.109.7.175: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Метод двоичного подъёма''' {{---}} один из самых простых методов для решения задачи [[Сведение задачи LCA к задаче RMQ|LCA]] в online. Он не использует метод решения задачи '''RMQ''' и основан на методе [[Динамическое программирование | динамического программирования]].&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Как и большинство '''on-line''' алгоритмов для решения задачи [[Сведение задачи LCA к задаче RMQ|LCA]], этот метод делает сначала препроцессинг, чтобы потом отвечать на запросы.&lt;br /&gt;
===Препроцессинг===&lt;br /&gt;
Препроцессинг заключается в том, чтобы посчитать функцию: &amp;lt;tex&amp;gt; dp[v][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; шагов, причём если мы пришли в корень, то мы там и останемся.&lt;br /&gt;
Для этого сначала обойдем дерево в глубину, и для каждой вершины запишем номер её родителя &amp;lt;tex&amp;gt; p[v] &amp;lt;/tex&amp;gt; и глубину вершины в подвешенном дереве &amp;lt;tex&amp;gt; d[v] &amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; {{---}} корень, то &amp;lt;tex&amp;gt; p[v] = v &amp;lt;/tex&amp;gt;. Тогда для функции &amp;lt;tex&amp;gt; dp &amp;lt;/tex&amp;gt; есть рекуррентная формула:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;dp[v][i]= \begin{cases}&lt;br /&gt;
p[v] &amp;amp; i = 0,\\&lt;br /&gt;
dp[dp[v][i - 1]][i - 1] &amp;amp; i \: &amp;gt; \: 0.&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы отвечать на запросы нам нужны будут только те значения &amp;lt;tex&amp;gt; dp[v][i] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; i \leqslant \log_2{n} &amp;lt;/tex&amp;gt;, ведь при больших &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt; dp[v][i] &amp;lt;/tex&amp;gt; будет номером корня. &lt;br /&gt;
&lt;br /&gt;
Всего состояний динамики &amp;lt;tex&amp;gt; O(n \log{n})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} это количество вершин в дереве. Каждое состояние считается за &amp;lt;tex&amp;gt; O(1) &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;
===Ответы на запросы===&lt;br /&gt;
Ответы на запросы будут происходить за время &amp;lt;tex&amp;gt; O(\log{n})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Для ответа на запрос заметим сначала, что если &amp;lt;tex&amp;gt; c = LCA(v, u) &amp;lt;/tex&amp;gt;, для некоторых &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; d[c] \leqslant \min(d[v], d[u])&amp;lt;/tex&amp;gt;. Поэтому если &amp;lt;tex&amp;gt; d[v] &amp;lt; d[u] &amp;lt;/tex&amp;gt;, то пройдём от вершины &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; (d[u] - d[v]) &amp;lt;/tex&amp;gt; шагов вверх, это и будет новое значение &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; и это можно сделать за &amp;lt;tex&amp;gt; O(\log{n}) &amp;lt;/tex&amp;gt;. Можно записать число &amp;lt;tex&amp;gt; (d[u] - d[v]) &amp;lt;/tex&amp;gt; в двоичной системе, это представление этого число в виде суммы степеней двоек, &amp;lt;tex&amp;gt; 2 ^ {i_1} + 2 ^ {i_2} + \ldots + 2 ^ {i_l} &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt; i_j&amp;lt;/tex&amp;gt; пройти вверх последовательно из вершины &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; dp[u][i_j] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Дальше считаем, что &amp;lt;tex&amp;gt; d[v] = d[u] &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt; v = 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; v \neq u &amp;lt;/tex&amp;gt;, то найдём такие вершины &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, такие что &amp;lt;tex&amp;gt; x \neq y &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{---}} предок &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; {{---}} предок &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; p[x] = p[y] &amp;lt;/tex&amp;gt;. Тогда ответом на запрос будет &amp;lt;tex&amp;gt; p[x] &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Научимся находить эти вершины &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;. Для этого сначала инициализируем &amp;lt;tex&amp;gt; x = v &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y = u &amp;lt;/tex&amp;gt;. Дальше на каждом шаге находим такое максимальное &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt; dp[x][k] \neq dp[y][k] &amp;lt;/tex&amp;gt;. И проходим из вершин &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; 2 ^ k &amp;lt;/tex&amp;gt; шагов вверх. Если такого &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; найти нельзя, то значения &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, это те самые вершины, которые нам требуется найти, ведь &amp;lt;tex&amp;gt; p[x] = dp[x][0] = dp[y][0] = p[y] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оценим время работы. Заметим, что найденные &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; строго убывают. Во-первых, потому что мы находим на каждом шаге максимальное значение &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, а во-вторых, два раза подряд мы одно и то же &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; получить не можем, так как тогда получилось бы, что можно пройти &amp;lt;tex&amp;gt; 2 ^ k + 2 ^ k = 2 ^ {k + 1}&amp;lt;/tex&amp;gt; шагов, а значит вместо первого &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, мы бы нашли &amp;lt;tex&amp;gt; k + 1 &amp;lt;/tex&amp;gt;. А, значит, всего &amp;lt;tex&amp;gt; O(\log{n}) &amp;lt;/tex&amp;gt; значений &amp;lt;tex&amp;gt; k &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;
&amp;lt;code&amp;gt;&lt;br /&gt;
   '''function''' preprocess():&lt;br /&gt;
      '''int[]''' p = dfs(0)&lt;br /&gt;
      '''for''' i = 1 '''to''' n&lt;br /&gt;
         dp[i][0] = p[i]&lt;br /&gt;
      '''for''' j = 1 '''to''' log(n)&lt;br /&gt;
         '''for''' i = 1 '''to''' n&lt;br /&gt;
            dp[i][j] = dp[dp[i][j - 1]][j - 1]&lt;br /&gt;
   &lt;br /&gt;
   '''int''' lca('''int''' v, '''int''' u):&lt;br /&gt;
      '''if''' d[v] &amp;gt; d[u]&lt;br /&gt;
         swap(v, u)&lt;br /&gt;
      '''for''' i = log(n) '''downto''' 0&lt;br /&gt;
         '''if''' d[dp[u][i]] - d[v] &amp;gt;= 0 &amp;lt;tex&amp;gt;\geqslant 2 ^ i &amp;lt;/tex&amp;gt;&lt;br /&gt;
            u = dp[u][i]&lt;br /&gt;
      '''if''' v == u&lt;br /&gt;
         '''return''' v&lt;br /&gt;
      '''for''' i = log(n) '''downto''' 0&lt;br /&gt;
         '''if''' dp[v][i] != dp[u][i]&lt;br /&gt;
            v = dp[v][i]&lt;br /&gt;
            u = dp[u][i]&lt;br /&gt;
      '''return''' p[v]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Сведение задачи LCA к задаче RMQ]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Lowest_common_ancestor Wikipedia: LCA]&lt;br /&gt;
* [http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=lowestCommonAncestor TopCoder tutorial: RMQ and LCA]&lt;br /&gt;
* [http://e-maxx.ru/algo/lca_simpler MAXimal :: algo :: Метод двоичного подъёма ]&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о наименьшем общем предке]]&lt;/div&gt;</summary>
		<author><name>212.109.7.175</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D0%B4%D1%8A%D1%91%D0%BC%D0%B0&amp;diff=72102</id>
		<title>Метод двоичного подъёма</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B4%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D0%B4%D1%8A%D1%91%D0%BC%D0%B0&amp;diff=72102"/>
				<updated>2020-01-11T21:25:58Z</updated>
		
		<summary type="html">&lt;p&gt;212.109.7.175: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Метод двоичного подъёма''' {{---}} один из самых простых методов для решения задачи [[Сведение задачи LCA к задаче RMQ|LCA]] в online. Он не использует метод решения задачи '''RMQ''' и основан на методе [[Динамическое программирование | динамического программирования]].&lt;br /&gt;
==Описание алгоритма==&lt;br /&gt;
Как и большинство '''on-line''' алгоритмов для решения задачи [[Сведение задачи LCA к задаче RMQ|LCA]], этот метод делает сначала препроцессинг, чтобы потом отвечать на запросы.&lt;br /&gt;
===Препроцессинг===&lt;br /&gt;
Препроцессинг заключается в том, чтобы посчитать функцию: &amp;lt;tex&amp;gt; dp[v][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; шагов, причём если мы пришли в корень, то мы там и останемся.&lt;br /&gt;
Для этого сначала обойдем дерево в глубину, и для каждой вершины запишем номер её родителя &amp;lt;tex&amp;gt; p[v] &amp;lt;/tex&amp;gt; и глубину вершины в подвешенном дереве &amp;lt;tex&amp;gt; d[v] &amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; {{---}} корень, то &amp;lt;tex&amp;gt; p[v] = v &amp;lt;/tex&amp;gt;. Тогда для функции &amp;lt;tex&amp;gt; dp &amp;lt;/tex&amp;gt; есть рекуррентная формула:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;dp[v][i]= \begin{cases}&lt;br /&gt;
p[v] &amp;amp; i = 0,\\&lt;br /&gt;
dp[dp[v][i - 1]][i - 1] &amp;amp; i \: &amp;gt; \: 0.&lt;br /&gt;
\end{cases}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы отвечать на запросы нам нужны будут только те значения &amp;lt;tex&amp;gt; dp[v][i] &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; i \leqslant \log_2{n} &amp;lt;/tex&amp;gt;, ведь при больших &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; значение &amp;lt;tex&amp;gt; dp[v][i] &amp;lt;/tex&amp;gt; будет номером корня. &lt;br /&gt;
&lt;br /&gt;
Всего состояний динамики &amp;lt;tex&amp;gt; O(n \log{n})&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; {{---}} это количество вершин в дереве. Каждое состояние считается за &amp;lt;tex&amp;gt; O(1) &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;
===Ответы на запросы===&lt;br /&gt;
Ответы на запросы будут происходить за время &amp;lt;tex&amp;gt; O(\log{n})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Для ответа на запрос заметим сначала, что если &amp;lt;tex&amp;gt; c = LCA(v, u) &amp;lt;/tex&amp;gt;, для некоторых &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; d[c] \leqslant \min(d[v], d[u])&amp;lt;/tex&amp;gt;. Поэтому если &amp;lt;tex&amp;gt; d[v] &amp;lt; d[u] &amp;lt;/tex&amp;gt;, то пройдём от вершины &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; (d[u] - d[v]) &amp;lt;/tex&amp;gt; шагов вверх, это и будет новое значение &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; и это можно сделать за &amp;lt;tex&amp;gt; O(\log{n}) &amp;lt;/tex&amp;gt;. Можно записать число &amp;lt;tex&amp;gt; (d[u] - d[v]) &amp;lt;/tex&amp;gt; в двоичной системе, это представление этого число в виде суммы степеней двоек, &amp;lt;tex&amp;gt; 2 ^ {i_1} + 2 ^ {i_2} + \ldots + 2 ^ {i_l} &amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt; i_j&amp;lt;/tex&amp;gt; пройти вверх последовательно из вершины &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; dp[u][i_j] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Дальше считаем, что &amp;lt;tex&amp;gt; d[v] = d[u] &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt; v = 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; v \neq u &amp;lt;/tex&amp;gt;, то найдём такие вершины &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, такие что &amp;lt;tex&amp;gt; x \neq y &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{---}} предок &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; {{---}} предок &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; p[x] = p[y] &amp;lt;/tex&amp;gt;. Тогда ответом на запрос будет &amp;lt;tex&amp;gt; p[x] &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Научимся находить эти вершины &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;. Для этого сначала инициализируем &amp;lt;tex&amp;gt; x = v &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y = u &amp;lt;/tex&amp;gt;. Дальше на каждом шаге находим такое максимальное &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt; dp[x][k] \neq dp[y][k] &amp;lt;/tex&amp;gt;. И проходим из вершин &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; 2 ^ k &amp;lt;/tex&amp;gt; шагов вверх. Если такого &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; найти нельзя, то значения &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;, это те самые вершины, которые нам требуется найти, ведь &amp;lt;tex&amp;gt; p[x] = dp[x][0] = dp[y][0] = p[y] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оценим время работы. Заметим, что найденные &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; строго убывают. Во-первых, потому что мы находим на каждом шаге максимальное значение &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, а во-вторых, два раза подряд мы одно и то же &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; получить не можем, так как тогда получилось бы, что можно пройти &amp;lt;tex&amp;gt; 2 ^ k + 2 ^ k = 2 ^ {k + 1}&amp;lt;/tex&amp;gt; шагов, а значит вместо первого &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, мы бы нашли &amp;lt;tex&amp;gt; k + 1 &amp;lt;/tex&amp;gt;. А, значит, всего &amp;lt;tex&amp;gt; O(\log{n}) &amp;lt;/tex&amp;gt; значений &amp;lt;tex&amp;gt; k &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;
&amp;lt;code&amp;gt;&lt;br /&gt;
   '''function''' preprocess():&lt;br /&gt;
      '''int[]''' p = dfs(0)&lt;br /&gt;
      '''for''' i = 1 '''to''' n&lt;br /&gt;
         dp[i][0] = p[i]&lt;br /&gt;
      '''for''' j = 1 '''to''' log(n)&lt;br /&gt;
         '''for''' i = 1 '''to''' n&lt;br /&gt;
            dp[i][j] = dp[dp[i][j - 1]][j - 1]&lt;br /&gt;
   &lt;br /&gt;
   '''int''' lca('''int''' v, '''int''' u):&lt;br /&gt;
      '''if''' d[v] &amp;gt; d[u]&lt;br /&gt;
         swap(v, u)&lt;br /&gt;
      '''for''' i = log(n) '''downto''' 0&lt;br /&gt;
         '''if''' d[dp[u][k]] - d[v] &amp;gt;= 0 &amp;lt;tex&amp;gt;\geqslant 2 ^ i &amp;lt;/tex&amp;gt;&lt;br /&gt;
            u = dp[u][i]&lt;br /&gt;
      '''if''' v == u&lt;br /&gt;
         '''return''' v&lt;br /&gt;
      '''for''' i = log(n) '''downto''' 0&lt;br /&gt;
         '''if''' dp[v][i] != dp[u][i]&lt;br /&gt;
            v = dp[v][i]&lt;br /&gt;
            u = dp[u][i]&lt;br /&gt;
      '''return''' p[v]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Сведение задачи LCA к задаче RMQ]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Lowest_common_ancestor Wikipedia: LCA]&lt;br /&gt;
* [http://www.topcoder.com/tc?module=Static&amp;amp;d1=tutorials&amp;amp;d2=lowestCommonAncestor TopCoder tutorial: RMQ and LCA]&lt;br /&gt;
* [http://e-maxx.ru/algo/lca_simpler MAXimal :: algo :: Метод двоичного подъёма ]&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Задача о наименьшем общем предке]]&lt;/div&gt;</summary>
		<author><name>212.109.7.175</name></author>	</entry>

	</feed>