<?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=Sergey+Keik</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=Sergey+Keik"/>
		<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/Sergey_Keik"/>
		<updated>2026-04-15T08:30:51Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%BB%D0%B5%D1%81%D0%B0_%D0%BA%D0%BE%D1%80%D0%BD%D0%B5%D0%B2%D1%8B%D1%85_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D1%8C%D0%B5%D0%B2)&amp;diff=82660</id>
		<title>СНМ (реализация с помощью леса корневых деревьев)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_%D0%BB%D0%B5%D1%81%D0%B0_%D0%BA%D0%BE%D1%80%D0%BD%D0%B5%D0%B2%D1%8B%D1%85_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D1%8C%D0%B5%D0%B2)&amp;diff=82660"/>
				<updated>2022-08-09T11:45:04Z</updated>
		
		<summary type="html">&lt;p&gt;Sergey Keik: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная реализация СНМ позволяет добиться наилучшей асимптотики при работе с этой структурой данных. А именно, обе операции (&amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt;) выполняются в среднем за практически константное время.&lt;br /&gt;
==Реализация==&lt;br /&gt;
Каждое множество хранится в виде дерева. Элементы множества хранятся в вершинах дерева. У каждого множества есть его представитель {{---}} один из элементов этого множества, он хранится в корне дерева. В каждом узле, кроме корня, хранится ссылка на &amp;quot;родителя&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
При объединении двух множеств, корень одного дерева подвешивается к другому (операция ''&amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt;''). Таким образом, чтобы определить, в каком множестве находится элемент достаточно пройтись по ссылкам по дереву вверх до корня (операция ''&amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt;'').&lt;br /&gt;
&lt;br /&gt;
Без использования дополнительных &amp;quot;улучшений&amp;quot;, такое дерево может выродиться в линейный список, где &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; будет работать за линейное время, и никакого выигрыша по сравнению с [[СНМ(наивные_реализации)|наивными реализациями]] не будет. Выигрыш в скорости можно получить, используя две эвристики: '''объединение по рангу''' (union by rank) и '''сжатие пути''' (path compression).&lt;br /&gt;
&lt;br /&gt;
===Объединение по рангу===&lt;br /&gt;
Эта эвристика аналогична [[СНМ(списки_с_весовой_эвристикой)|весовой эвристике у связных списков]]. Идея в том, чтобы при объединении подвешивать дерево с меньшей глубиной к дереву с большей. &lt;br /&gt;
&lt;br /&gt;
Вместо того, чтобы явно хранить высоту дерева, можно хранить его ранг, который по сути является некой верхней оценкой высоты дерева. У дерева, состоящего ровно из одного элемента ранг равен &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. При объединении дерево с меньшим рангом подвешивается к дереву с большим, и ранг объединенного дерева становится равным большему из этих двух рангов. Если ранги объединяемых деревьев равны, то не важно какое к какому дереву подвешивать, но ранг объединенного дерева следует делать большим на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Сжатие пути===&lt;br /&gt;
Эта эвристика несколько модифицирует операцию ''&amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt;''. Операция &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; вызывается для элемента &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, проходит через несколько вершин и попадает в корень. Все пройденные в этом процессе вершины принадлежат тому же множеству, что и &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Поэтому мы можем подвесить (изменить ссылки) эти вершины напрямую к корню дерева и, таким образом, уменьшить его высоту. При нерекурсивной реализации операция ''&amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt;'' становится двухпроходной.&lt;br /&gt;
&lt;br /&gt;
===Псевдокод===&lt;br /&gt;
Для реализации СНМ будем поддерживать следующие массивы: &amp;lt;tex&amp;gt;p[x]&amp;lt;/tex&amp;gt; {{---}} массив &amp;quot;родителей&amp;quot;, &amp;lt;tex&amp;gt;r[x]&amp;lt;/tex&amp;gt; {{---}} массив рангов.&lt;br /&gt;
===='''get'''====&lt;br /&gt;
 '''function''' '''get'''(x: '''int'''): '''int'''&lt;br /&gt;
   '''if''' p[x] != x&lt;br /&gt;
     p[x] = get(p[x])&lt;br /&gt;
   '''return''' p[x]&lt;br /&gt;
&lt;br /&gt;
===='''union'''====&lt;br /&gt;
 '''function''' '''union'''(x: '''int''', y: '''int'''):&lt;br /&gt;
   x = get(x)&lt;br /&gt;
   y = get(y)&lt;br /&gt;
   '''if''' x == y&lt;br /&gt;
     '''return'''&lt;br /&gt;
   '''if''' r[x] == r[y]&lt;br /&gt;
     r[x]++&lt;br /&gt;
   '''if''' r[x] &amp;lt; r[y]&lt;br /&gt;
     p[x] = y&lt;br /&gt;
   '''else'''&lt;br /&gt;
     p[y] = x&lt;br /&gt;
	 &lt;br /&gt;
Также возможна реализация функции &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; без использования &amp;lt;tex&amp;gt;\mathrm{O(\log n)}&amp;lt;/tex&amp;gt; дополнительной памяти.&lt;br /&gt;
&lt;br /&gt;
===='''get'''====&lt;br /&gt;
 '''function''' '''get'''(x: '''int'''): '''int'''&lt;br /&gt;
  root = x&lt;br /&gt;
  '''while''' p[root] != root&lt;br /&gt;
    root = p[root]&lt;br /&gt;
  i = x&lt;br /&gt;
  '''while''' p[i] != i&lt;br /&gt;
    j = p[i]&lt;br /&gt;
    p[i] = root&lt;br /&gt;
    i = j&lt;br /&gt;
  '''return''' root&lt;br /&gt;
&lt;br /&gt;
==Асимптотика==&lt;br /&gt;
:''см. также [[Анализ_реализации_с_ранговой_эвристикой|Анализ реализации с ранговой эвристикой]]''&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border = 1&lt;br /&gt;
|-&lt;br /&gt;
!Операция !! Истинное время !! Амортизированное время&lt;br /&gt;
|- style = &amp;quot;text-align = center&amp;quot;&lt;br /&gt;
| ''&amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt;''                  || &amp;lt;tex&amp;gt;\mathrm{O(\log n)}&amp;lt;/tex&amp;gt;        ||  &amp;lt;tex&amp;gt;\mathrm{O(\mathrm{\alpha(m, n)})}&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
| ''&amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt;''                || &amp;lt;tex&amp;gt;\mathrm{O(\log n)}&amp;lt;/tex&amp;gt;            ||  &amp;lt;tex&amp;gt;\mathrm{O(\mathrm{\alpha(m, n)})}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
Где &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; {{---}} общее количество операций, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} полное количество элементов, &amp;lt;tex&amp;gt;\mathrm{\alpha(m, n)}&amp;lt;/tex&amp;gt; {{---}} функция, обратная к функции Аккермана (если &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; операций &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n&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;2^k&amp;lt;/tex&amp;gt; элементов. Из этого свойства следует, что глубина множества с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементами есть &amp;lt;tex&amp;gt;\mathrm{O(\log n)}&amp;lt;/tex&amp;gt;, а значит и время работы операции &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; является логарифмическим.&lt;br /&gt;
&lt;br /&gt;
Будем доказывать данное свойство по индукции. Для &amp;lt;tex&amp;gt;k = 0&amp;lt;/tex&amp;gt;, очевидно, в множестве содержится &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; вершина. Пусть для множеств ранга &amp;lt;tex&amp;gt;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;k - 1&amp;lt;/tex&amp;gt;. Но тогда из предположения индукции в новом множестве действительно будет &amp;lt;tex&amp;gt;2^k&amp;lt;/tex&amp;gt; вершин, что и требовалось доказать.&lt;br /&gt;
&lt;br /&gt;
===Функция Аккермана===&lt;br /&gt;
&lt;br /&gt;
Функция Аккермана определяется следующим рекуррентным соотношением для целых неотрицательных чисел &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathrm{A(m, n)} = \begin{cases}&lt;br /&gt;
 2^n, &amp;amp; m = 1 \\&lt;br /&gt;
 2, &amp;amp; m &amp;gt; 1, n = 0 \\&lt;br /&gt;
 \mathrm{A(m - 1, A(m, n - 1))}, &amp;amp; m &amp;gt; 1, n &amp;gt; 0&lt;br /&gt;
\end{cases} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таблица значений функции Аккермана:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border = 1&lt;br /&gt;
|-&lt;br /&gt;
!&amp;lt;tex&amp;gt;\mathbf{m \backslash n}&amp;lt;/tex&amp;gt; !! &amp;lt;tex&amp;gt;\mathbf{0}&amp;lt;/tex&amp;gt; !! &amp;lt;tex&amp;gt;\mathbf{1}&amp;lt;/tex&amp;gt; !! &amp;lt;tex&amp;gt;\mathbf{2}&amp;lt;/tex&amp;gt; !! &amp;lt;tex&amp;gt;\mathbf{3}&amp;lt;/tex&amp;gt; !! &amp;lt;tex&amp;gt;\mathbf{4}&amp;lt;/tex&amp;gt; !! &amp;lt;tex&amp;gt;\mathbf{5}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-style = &amp;quot;text-align = center&amp;quot;&lt;br /&gt;
! &amp;lt;tex&amp;gt;\mathbf{1}&amp;lt;/tex&amp;gt; &lt;br /&gt;
| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; ||  &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;16&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;32&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;tex&amp;gt;\mathbf{2}&amp;lt;/tex&amp;gt; &lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;16&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;65536&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;2^{2^{16}}&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;2^{2^{2^{16}}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;tex&amp;gt;\mathbf{3}&amp;lt;/tex&amp;gt; &lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;16&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\underbrace{2^{2^{\cdot^{\cdot^{\cdot^2}}}}}_{17}&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\underbrace{2^{2^{\cdot^{\cdot^{\cdot^2}}}}}_{A(3, 2)}&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\cdots&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\cdots&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;tex&amp;gt;\mathbf{4}&amp;lt;/tex&amp;gt; &lt;br /&gt;
| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\underbrace{2^{2^{\cdot^{\cdot^{\cdot^2}}}}}_{17}&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\cdots&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\cdots&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\cdots&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\cdots&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Функция, обратная функции Аккермана &amp;lt;tex&amp;gt;\mathrm{\alpha(m, n)}&amp;lt;/tex&amp;gt;, равна минимальному &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; такому, что &amp;lt;tex&amp;gt;\mathrm{A \left (i, \left [\dfrac{m}{n} \right ] \right )} \geqslant \log n&amp;lt;/tex&amp;gt;. Как видно из таблицы значений для функции Аккермана, обратная функция для любых значений, которые могут возникнуть при решении прикладных задач, не превышает 4, то есть можно считать, что операция &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt; выполняется за константное время.&lt;br /&gt;
&lt;br /&gt;
===Анализ реализации с ранговой эвристикой===&lt;br /&gt;
&lt;br /&gt;
Проведем анализ реализации с ранговой эвристикой. Будем доказывать, что амортизационная стоимость &amp;lt;tex&amp;gt; \mathrm{get} = \mathrm{O(\log^{*}n)}  &amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition='''Итерированный логарифм''' (англ. ''Iterated logarithm'') &amp;lt;tex&amp;gt;\mathrm{\log^*n}&amp;lt;/tex&amp;gt; — минимальное число логарифмирований &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, необходимое для получения значения, не превосходящего &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
'''Пример''': &amp;lt;tex&amp;gt;\mathrm{\log^*_2 16} = 3&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; операций &amp;lt;tex&amp;gt; \mathrm{union}  &amp;lt;/tex&amp;gt; и  &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt; операций  &amp;lt;tex&amp;gt; \mathrm{get} &amp;lt;/tex&amp;gt;. Можем считать, что число операций &amp;lt;tex&amp;gt; \mathrm{union}  &amp;lt;/tex&amp;gt; равно числу элементов множества, так как количество операций &amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt; не превосходит количество элементов множества &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Заметим, что &amp;lt;tex&amp;gt;m\geqslant n&amp;lt;/tex&amp;gt;, так как при каждом вызове операции &amp;lt;tex&amp;gt;\mathrm{union}&amp;lt;/tex&amp;gt; дважды вызывается операция &amp;lt;tex&amp;gt;\mathrm{get}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Не теряя общности, будем считать, что &amp;lt;tex&amp;gt; \mathrm{union} &amp;lt;/tex&amp;gt; принимает в качестве аргументов представителей,&lt;br /&gt;
то есть &amp;lt;tex&amp;gt; \mathrm{union(v_1,v_2)} &amp;lt;/tex&amp;gt; заменяем на  &amp;lt;tex&amp;gt; \mathrm{union(get(v_1),get(v_2))} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оценим стоимость операции &amp;lt;tex&amp;gt; \mathrm{get(v)} &amp;lt;/tex&amp;gt;.  &lt;br /&gt;
Обозначим &amp;lt;tex&amp;gt; \mathrm{R(v)} &amp;lt;/tex&amp;gt; — ранг вершины, &amp;lt;tex&amp;gt;\mathrm{P(v)}&amp;lt;/tex&amp;gt; — представитель множества, содержащего &amp;lt;tex&amp;gt;\mathrm{v}&amp;lt;/tex&amp;gt;,&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{L(v)} &amp;lt;/tex&amp;gt; — отец вершины,&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{K(v)} &amp;lt;/tex&amp;gt; — количество вершин в поддереве, корнем которого является &amp;lt;tex&amp;gt;\mathrm{v}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{R(P(v))} \geqslant \mathrm{R(v)} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;\mathrm{v}&amp;lt;/tex&amp;gt; — представитель множества, то &amp;lt;tex&amp;gt;\mathrm{P(v)}=\mathrm{v}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{R(P(v))} = \mathrm{R(v)} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Иначе, из принципа работы функции &amp;lt;tex&amp;gt; \mathrm{union} &amp;lt;/tex&amp;gt; следует:&lt;br /&gt;
#&amp;lt;tex&amp;gt; \mathrm{R(L(v))}&amp;gt;\mathrm{R(v)} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Между  &amp;lt;tex&amp;gt; \mathrm{v} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{P(v)} &amp;lt;/tex&amp;gt; существует путь вида: &amp;lt;tex&amp;gt; \mathrm{v} \rightarrow \mathrm{L(v)} \rightarrow \mathrm{L(L(v))} \rightarrow \dots \rightarrow \mathrm{P(v)} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Записав неравенство из первого пункта вдоль пути из второго пункта, получаем требуемое.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{R(v)} = i \Rightarrow {\mathrm{K(v)}} \geqslant  {2^i}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем по индукции: &lt;br /&gt;
&lt;br /&gt;
Для &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; равенство очевидно.&lt;br /&gt;
Ранг вершины станет равным &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; при объединении поддеревьев ранга &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt;, следовательно:&lt;br /&gt;
&amp;lt;tex&amp;gt;\mathrm{K(v)} \geqslant \mathrm{K(v_1)} + \mathrm{K(v_2)} \geqslant 2^{i-1}+2^{i-1} \geqslant 2^i &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Из последнего утверждения следует:&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{R(v)} \leqslant \log_2n &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
Количество вершин ранга &amp;lt;tex&amp;gt; i \leqslant \dfrac{n}  {2^i} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
Если бы это было не так, то просуммировав количество вершин всех рангов, мы получили бы число большее &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Это противоречит условию, по которому &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; — число всех вершин. Значит утверждение верно.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Амортизационная стоимость &amp;lt;tex&amp;gt; \mathrm{get} = \mathrm{O(\log^{*}n)}  &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Рассмотрим все вызовы функции &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt;. В процессе выполнения каждой операции двигаемся вверх по одному из деревьев, заканчивая поиск в его корне. Если вершина &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; не корень и не сын корня, то во время рекурсивных вызовов функции &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt; текущее значение &amp;lt;tex&amp;gt;\mathrm{R(L(u))}&amp;lt;/tex&amp;gt; возрастает.&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; — количество вызовов операции &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; — количество вызовов операции &amp;lt;tex&amp;gt;\mathrm{union(v, u)}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;m\geqslant n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Разделим все вершины на &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt; типа:&lt;br /&gt;
&lt;br /&gt;
:1. &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; — корень. Таких вызовов &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt; будет ровно &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:2. &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; — сын корня. Таких вызовов &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt; будет не больше чем &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Оставшиеся вершины разделим на:&lt;br /&gt;
:3. Быстро растущие вызовы — такие что &amp;lt;tex&amp;gt;\mathrm{R(P(u))} \geqslant i^{\mathrm{R(u)}}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; — число из диапазона &amp;lt;tex dpi=&amp;quot;150&amp;quot;&amp;gt;e ^{\frac{1}{e}} &amp;lt; i &amp;lt; 2&amp;lt;/tex&amp;gt; &amp;lt;tex dpi=&amp;quot;150&amp;quot;&amp;gt;(e ^{\frac{1}{e}}\approx &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;1.44&amp;lt;/tex&amp;gt;&amp;lt;tex dpi=&amp;quot;150&amp;quot;&amp;gt;)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
:4. Медленно растущие вызовы — &amp;lt;tex&amp;gt;\mathrm{R(P(u))} &amp;lt; i^{\mathrm{R(u)}}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для первых двух типов вершин одна операция &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt; работает за истинное время &amp;lt;tex&amp;gt;\mathrm{O(1)}&amp;lt;/tex&amp;gt;, поэтому их суммарное время работы не превышает &amp;lt;tex&amp;gt;2\cdot m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При каждом вложенном вызове функции &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt; для вершин третьего типа ранг по условию возрастает до &amp;lt;tex&amp;gt;i^{\mathrm{R(u)}}&amp;lt;/tex&amp;gt;. Ранг вершины может меняться в пределах от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;\log_2n&amp;lt;/tex&amp;gt;. Значит количество рекурсивных вызовов равняется количеству возведений в степень &amp;lt;tex&amp;gt;\mathrm{R(n)}&amp;lt;/tex&amp;gt; числа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;,&lt;br /&gt;
необходимых для достижения числа &amp;lt;tex&amp;gt;\log_2n&amp;lt;/tex&amp;gt;. Или что то же самое, количеству логарифмирований по основанию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; числа &amp;lt;tex&amp;gt;\log_2n&amp;lt;/tex&amp;gt; для получения &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и еще одному логарифмированию для получения &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. Количество логарифмирований описывается функцией &amp;lt;tex dpi=&amp;quot;130&amp;quot;&amp;gt;\log^*_{i} \left (\log_2 n  \right )&amp;lt;/tex&amp;gt;. С учетом последнего логарифмирования формула примет вид &amp;lt;tex dpi=&amp;quot;130&amp;quot;&amp;gt;\log^*_{i}n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда время работы &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; быстро растущих вызовов равно &amp;lt;tex&amp;gt;\mathrm{O(m\cdot \log^* n)}&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;\dfrac{n}{2^k}&amp;lt;/tex&amp;gt;, то суммарное время работы медленно растущих вызовов равно&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex dpi=&amp;quot;150&amp;quot;&amp;gt;\sum_u \limits i^{\mathrm{R(u)}}=\sum_{k=0}^{\log n} \limits \sum_{\mathrm{{R(u)}=k}} \limits i^k \leqslant \sum_{k=0}^{\log n} \limits i^k \cdot \frac{n}{2^k} \leqslant n \cdot \sum_{k=0}^{\log n} \limits \dfrac{i^k}{2^k} = \mathrm{O(n)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
В итоге получаем, что суммарное время работы операции &amp;lt;tex&amp;gt;\mathrm{get(u)}&amp;lt;/tex&amp;gt; равняется &amp;lt;tex&amp;gt;T = \mathrm{O(m)} + \mathrm{O(m\cdot \log^* n)} +\mathrm{O(n)} = \mathrm{O(m\cdot \log^*n + n)}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
С учетом того факта что &amp;lt;tex&amp;gt;m\geqslant n&amp;lt;/tex&amp;gt;, амортизированное время работы равно &amp;lt;tex&amp;gt;\mathrm{O(\log^* n)}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (наивные реализации)]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств {{---}} описание этой реализации на habrahabr.ru]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Функция_Аккермана  Функция Аккермана {{---}} Википедия]&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн. Алгоритмы. Построение и анализ —  Вильямс, 2010. - стр 589. — ISBN 978-5-8459-0857-4&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Структуры данных]]&lt;/div&gt;</summary>
		<author><name>Sergey Keik</name></author>	</entry>

	</feed>