<?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=Nastya</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=Nastya"/>
		<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/Nastya"/>
		<updated>2026-08-04T13:36:28Z</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_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=39007</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=39007"/>
				<updated>2014-06-13T12:05:36Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''struct''' SetItem &lt;br /&gt;
     '''int''' data       &lt;br /&gt;
     '''int''' head&lt;br /&gt;
     '''SetItem''' next&lt;br /&gt;
     '''SetItem''' tail&lt;br /&gt;
&lt;br /&gt;
 '''SetItem''' s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].head = s[i]         &lt;br /&gt;
         s[i].tail = s[i]&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find('''SetItem''' x):                        &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''SetItem''' x, '''SetItem''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y                         &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail                         &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null                         &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D0%BD%D0%B5%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D0%B5%D0%BA%D0%B0%D1%8E%D1%89%D0%B8%D1%85%D1%81%D1%8F_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2 Википедия: Система непересекающихся множеств]&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=39005</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=39005"/>
				<updated>2014-06-13T12:02:01Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''struct''' SetItem &lt;br /&gt;
     '''int''' data       &lt;br /&gt;
     '''int''' head&lt;br /&gt;
     '''SetItem''' next&lt;br /&gt;
     '''SetItem''' tail&lt;br /&gt;
&lt;br /&gt;
 '''SetItem''' s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find('''SetItem''' x):                        &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''SetItem''' x, '''SetItem''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y                         &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail                         &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null                         &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D0%BD%D0%B5%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D0%B5%D0%BA%D0%B0%D1%8E%D1%89%D0%B8%D1%85%D1%81%D1%8F_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2 Википедия: Система непересекающихся множеств]&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=39003</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=39003"/>
				<updated>2014-06-13T11:55:49Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Источники информации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''srtruct''' nameOfStruct &lt;br /&gt;
     int head&lt;br /&gt;
     *nameOfStruct next&lt;br /&gt;
     int data&lt;br /&gt;
&lt;br /&gt;
 nameOFStruct s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(nameOfStruct x):                   &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union(nameOfStruct x, nameOfStruct y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y                         &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail                         &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null                         &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D0%BD%D0%B5%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D0%B5%D0%BA%D0%B0%D1%8E%D1%89%D0%B8%D1%85%D1%81%D1%8F_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2 Википедия: Система непересекающихся множеств]&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=39002</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=39002"/>
				<updated>2014-06-13T11:52:12Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&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;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи  о дереве отрезков с произвольной ассоциативной бинарной операцией.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; res&amp;lt;/tex&amp;gt; {{---}} результат операции на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' query ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' neutral&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].res&lt;br /&gt;
        '''return''' query (node * 2 + 1, a, b) &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; query (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Реализация запроса в дереве отрезков снизу]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=39001</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=39001"/>
				<updated>2014-06-13T11:49:20Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&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;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи  о дереве отрезков с произвольной ассоциативной бинарной операцией.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; res&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' query ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' neutral&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].res&lt;br /&gt;
        '''return''' query (node * 2 + 1, a, b) + query (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Реализация запроса в дереве отрезков снизу]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38999</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38999"/>
				<updated>2014-06-13T11:44:09Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&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;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи RSQ.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; sum&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' get_sum ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' 0&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].sum&lt;br /&gt;
        '''return''' get_sum (node * 2 + 1, a, b) + get_sum (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Реализация запроса в дереве отрезков снизу]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38998</id>
		<title>Реализация запроса в дереве отрезков снизу</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38998"/>
				<updated>2014-06-13T11:39:50Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее &amp;lt;tex&amp;gt;a \circ b&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:&lt;br /&gt;
# Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от  вклада ненужного нам поддерева. &lt;br /&gt;
# Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.&lt;br /&gt;
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| '''Реализация запроса снизу вверх''' || '''Ещё один пример'''&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х1.jpg|550px|]] || [[Файл:Запрос снизу №2х1.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х2.jpg|550px|]] || [[Файл:Запрос снизу №2х2.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х3.jpg|550px|]] || [[Файл:Запрос снизу №2х3.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х4.jpg|550px|]] || [[Файл:Запрос снизу №2х4.jpg|550px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
&lt;br /&gt;
Пусть результат считаем на отрезке &amp;lt;tex&amp;gt; [left, right] &amp;lt;/tex&amp;gt;. При этом значения &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные &amp;lt;tex&amp;gt;leftRes&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;rightRes&amp;lt;/tex&amp;gt; будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. &lt;br /&gt;
&lt;br /&gt;
   '''int''' query(left : '''int''', right : '''int'''):&lt;br /&gt;
      leftRes = ''neutral''&lt;br /&gt;
      rightRes = ''neutral''&lt;br /&gt;
      '''while''' left &amp;lt; right&lt;br /&gt;
         '''if''' left '''mod''' 2 == 0&lt;br /&gt;
            leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
         left = left '''div''' 2 &lt;br /&gt;
         '''if''' right '''mod''' 2 == 1&lt;br /&gt;
            rightRes = data[right] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
         right = (right - 1) '''div''' 2&lt;br /&gt;
      '''if''' left == right  &lt;br /&gt;
         leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
      '''return''' leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Реализация запроса в дереве отрезков сверху]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Википедия {{---}} Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006/algorithm Алгоритм]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38997</id>
		<title>Реализация запроса в дереве отрезков снизу</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38997"/>
				<updated>2014-06-13T11:38:08Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее &amp;lt;tex&amp;gt;a \circ b&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:&lt;br /&gt;
# Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от  вклада ненужного нам поддерева. &lt;br /&gt;
# Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.&lt;br /&gt;
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| '''Реализация запроса снизу вверх''' || '''Ещё один пример'''&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х1.jpg|550px|]] || [[Файл:Запрос снизу №2х1.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х2.jpg|550px|]] || [[Файл:Запрос снизу №2х2.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х3.jpg|550px|]] || [[Файл:Запрос снизу №2х3.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х4.jpg|550px|]] || [[Файл:Запрос снизу №2х4.jpg|550px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
&lt;br /&gt;
Пусть результат считаем на отрезке &amp;lt;tex&amp;gt; [left, right] &amp;lt;/tex&amp;gt;. При этом значения &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные &amp;lt;tex&amp;gt;leftRes&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;rightRes&amp;lt;/tex&amp;gt; будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. &lt;br /&gt;
&lt;br /&gt;
   '''int''' query(left : '''int''', right : '''int'''):&lt;br /&gt;
      leftRes = ''neutral''&lt;br /&gt;
      rightRes = ''neutral''&lt;br /&gt;
      '''while''' left &amp;lt; right&lt;br /&gt;
         '''if''' left '''mod''' 2 == 0&lt;br /&gt;
            leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
         left = left '''div''' 2 &lt;br /&gt;
         '''if''' right '''mod''' 2 == 1&lt;br /&gt;
            rightRes = data[right] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
         right = (right - 1) '''div''' 2&lt;br /&gt;
      '''if''' left == right  &lt;br /&gt;
         leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
      '''return''' leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Википедия {{---}} Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006/algorithm Алгоритм]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83 Реализация запроса в дереве отрезков сверху]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38975</id>
		<title>Реализация запроса в дереве отрезков снизу</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38975"/>
				<updated>2014-06-13T08:34:10Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее &amp;lt;tex&amp;gt;a \circ b&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:&lt;br /&gt;
# Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от  вклада ненужного нам поддерева. &lt;br /&gt;
# Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.&lt;br /&gt;
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| '''Реализация запроса снизу вверх''' || '''Ещё один пример'''&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х1.jpg|550px|]] || [[Файл:Запрос снизу №2х1.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х2.jpg|550px|]] || [[Файл:Запрос снизу №2х2.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х3.jpg|550px|]] || [[Файл:Запрос снизу №2х3.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х4.jpg|550px|]] || [[Файл:Запрос снизу №2х4.jpg|550px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
&lt;br /&gt;
Пусть результат считаем на отрезке [&amp;lt;tex&amp;gt; left, right &amp;lt;/tex&amp;gt;]. При этом значения &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные &amp;lt;tex&amp;gt;leftRes&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;rightRes&amp;lt;/tex&amp;gt; будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. &lt;br /&gt;
&lt;br /&gt;
   '''int''' query(left : '''int''', right : '''int'''):&lt;br /&gt;
      leftRes = ''neutral''&lt;br /&gt;
      rightRes = ''neutral''&lt;br /&gt;
      '''while''' left &amp;lt; right&lt;br /&gt;
         '''if''' left '''mod''' 2 == 0&lt;br /&gt;
            leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
         left = left '''div''' 2 &lt;br /&gt;
         '''if''' right '''mod''' 2 == 1&lt;br /&gt;
            rightRes = data[right] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
         right = (right - 1) '''div''' 2&lt;br /&gt;
      '''if''' left == right  &lt;br /&gt;
         leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
      '''return''' leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Википедия {{---}} Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006/algorithm Алгоритм]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83 Реализация запроса в дереве отрезков сверху]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%854.jpg&amp;diff=38973</id>
		<title>Файл:Запрос снизу №2х4.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%854.jpg&amp;diff=38973"/>
				<updated>2014-06-13T08:27:42Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №2х4.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%854.jpg&amp;diff=38972</id>
		<title>Файл:Запрос снизу №1х4.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%854.jpg&amp;diff=38972"/>
				<updated>2014-06-13T08:26:34Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №1х4.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%853.jpg&amp;diff=38971</id>
		<title>Файл:Запрос снизу №2х3.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%853.jpg&amp;diff=38971"/>
				<updated>2014-06-13T08:25:12Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №2х3.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%853.jpg&amp;diff=38970</id>
		<title>Файл:Запрос снизу №1х3.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%853.jpg&amp;diff=38970"/>
				<updated>2014-06-13T08:23:50Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №1х3.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%852.jpg&amp;diff=38969</id>
		<title>Файл:Запрос снизу №2х2.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%852.jpg&amp;diff=38969"/>
				<updated>2014-06-13T08:22:29Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №2х2.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%852.jpg&amp;diff=38968</id>
		<title>Файл:Запрос снизу №1х2.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%852.jpg&amp;diff=38968"/>
				<updated>2014-06-13T08:20:40Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №1х2.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%851.jpg&amp;diff=38967</id>
		<title>Файл:Запрос снизу №2х1.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%962%D1%851.jpg&amp;diff=38967"/>
				<updated>2014-06-13T08:17:06Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №2х1.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%851.jpg&amp;diff=38966</id>
		<title>Файл:Запрос снизу №1х1.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%851.jpg&amp;diff=38966"/>
				<updated>2014-06-13T08:14:06Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №1х1.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%851.jpg&amp;diff=38965</id>
		<title>Файл:Запрос снизу №1х1.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:%D0%97%D0%B0%D0%BF%D1%80%D0%BE%D1%81_%D1%81%D0%BD%D0%B8%D0%B7%D1%83_%E2%84%961%D1%851.jpg&amp;diff=38965"/>
				<updated>2014-06-13T07:56:15Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: загружена новая версия «Файл:Запрос снизу №1х1.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38964</id>
		<title>Реализация запроса в дереве отрезков снизу</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38964"/>
				<updated>2014-06-13T07:49:34Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее &amp;lt;tex&amp;gt;a \circ b&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:&lt;br /&gt;
# Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от  вклада ненужного нам поддерева. &lt;br /&gt;
# Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.&lt;br /&gt;
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| '''Реализация запроса снизу вверх''' || '''Ещё один пример'''&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х1.jpg|550px|]] || [[Файл:Запрос снизу №2х1.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х2.jpg|550px|]] || [[Файл:Запрос снизу №2х2.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х3.jpg|550px|]] || [[Файл:Запрос снизу №2х3.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х4.jpg|550px|]] || [[Файл:Запрос снизу №2х4.jpg|550px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
&lt;br /&gt;
Пусть результат считаем на отрезке [&amp;lt;tex&amp;gt; left, right &amp;lt;/tex&amp;gt;]. При этом значения &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные &amp;lt;tex&amp;gt;leftRes&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;rightRes&amp;lt;/tex&amp;gt; будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. &lt;br /&gt;
&lt;br /&gt;
   '''int''' query(left : '''int''', right : '''int'''):&lt;br /&gt;
      leftRes = ''neutral''&lt;br /&gt;
      rightRes = ''neutral''&lt;br /&gt;
      '''while''' left &amp;lt; right&lt;br /&gt;
         '''if''' left '''mod''' 2 == 0&lt;br /&gt;
            leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
         left = left '''div''' 2 &lt;br /&gt;
         '''if''' right '''mod''' 2 == 1&lt;br /&gt;
            rightRes = data[right] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
         right = (right - 1) '''div''' 2&lt;br /&gt;
      '''if''' left == right  &lt;br /&gt;
         leftRes = leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
      '''return''' leftRes &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; rightRes&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Википедия {{---}} Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006/algorithm Алгоритм]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38963</id>
		<title>Реализация запроса в дереве отрезков снизу</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38963"/>
				<updated>2014-06-13T07:45:46Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее &amp;lt;tex&amp;gt;a \circ b&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:&lt;br /&gt;
# Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от  вклада ненужного нам поддерева. &lt;br /&gt;
# Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.&lt;br /&gt;
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| '''Реализация запроса снизу вверх''' || '''Ещё один пример'''&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х1.jpg|550px|]] || [[Файл:Запрос снизу №2х1.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х2.jpg|550px|]] || [[Файл:Запрос снизу №2х2.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х3.jpg|550px|]] || [[Файл:Запрос снизу №2х3.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х4.jpg|550px|]] || [[Файл:Запрос снизу №2х4.jpg|550px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
&lt;br /&gt;
Пусть результат считаем на отрезке [&amp;lt;tex&amp;gt; left, right &amp;lt;/tex&amp;gt;]. При этом значения &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt;_&amp;lt;tex&amp;gt;res&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt;_&amp;lt;tex&amp;gt;res&amp;lt;/tex&amp;gt; будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. &lt;br /&gt;
&lt;br /&gt;
   '''int''' query(left : '''int''', right : '''int'''):&lt;br /&gt;
      left_res = ''neutral''&lt;br /&gt;
      right_res = ''neutral''&lt;br /&gt;
      '''while''' left &amp;lt; right&lt;br /&gt;
         '''if''' left '''mod''' 2 == 0&lt;br /&gt;
            left_res = left_res &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
         left = left '''div''' 2 &lt;br /&gt;
         '''if''' right '''mod''' 2 == 1&lt;br /&gt;
            right_res = data[right] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; right_res&lt;br /&gt;
         right = (right - 1) '''div''' 2&lt;br /&gt;
      '''if''' left == right  &lt;br /&gt;
         left_res = left_res &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
      '''return''' left_res &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; right_res&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Википедия {{---}} Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006/algorithm Алгоритм]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38962</id>
		<title>Реализация запроса в дереве отрезков снизу</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83&amp;diff=38962"/>
				<updated>2014-06-13T07:41:57Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Реализация запроса снизу вверх в дереве отрезков является, в отличие от [[Реализация запроса в дереве отрезков сверху| реализации запроса сверху вниз]], итеративным методом. Будем рассматривать абстрактную операцию, обладающую свойством ассоциативности, и обозначать ее a &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; b.&lt;br /&gt;
&lt;br /&gt;
[[Дерево отрезков. Построение|Построим дерево отрезков]] и установим границы отрезка на соответствующие им листья. Будем действовать в 3 этапа:&lt;br /&gt;
# Если элемент, попавший на левую границу, является правым сыном, то запишем в результат значение, полученное после выполнения нашей операции над предыдущим результатом и значением этого элемента, а левую границу перемещаем на один элемент вправо. Аналогично с правой границей (является ли она левым сыном). Таким образом мы учтем вклад нужной нам вершины и избавимся от  вклада ненужного нам поддерева. &lt;br /&gt;
# Устанавливаем границы отрезка на родительские элементы текущих границ. Это позволит узнать, входит ли полученный отрезок в искомый или нет. Повторяем этап 1, пока границы не пересекутся.&lt;br /&gt;
# Если после завершения цикла границы совпадут, значит полученный отрезок входит в искомый, и надо пересчитать результат.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
| '''Реализация запроса снизу вверх''' || '''Ещё один пример'''&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х1.jpg|550px|]] || [[Файл:Запрос снизу №2х1.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х2.jpg|550px|]] || [[Файл:Запрос снизу №2х2.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х3.jpg|550px|]] || [[Файл:Запрос снизу №2х3.jpg|550px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Запрос снизу №1х4.jpg|550px|]] || [[Файл:Запрос снизу №2х4.jpg|550px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
&lt;br /&gt;
Пусть результат считаем на отрезке [left, right]. При этом значения left и right, передающиеся в функцию, должны указывать на листья дерева (необходимо увеличить значение на индекс массива, с которого начинаются листья). Переменные left_res и right_res будут собирать значения на отрезках, отделившихся соответственно слева или справа от рассматриваемого. &lt;br /&gt;
&lt;br /&gt;
   '''int''' query(left : '''int''', right : '''int'''):&lt;br /&gt;
      left_res = ''neutral''&lt;br /&gt;
      right_res = ''neutral''&lt;br /&gt;
      '''while''' left &amp;lt; right&lt;br /&gt;
         '''if''' left '''mod''' 2 == 0&lt;br /&gt;
            left_res = left_res &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
         left = left '''div''' 2 &lt;br /&gt;
         '''if''' right '''mod''' 2 == 1&lt;br /&gt;
            right_res = data[right] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; right_res&lt;br /&gt;
         right = (right - 1) '''div''' 2&lt;br /&gt;
      '''if''' left == right  &lt;br /&gt;
         left_res = left_res &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; data[left]&lt;br /&gt;
      '''return''' left_res &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; right_res&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Википедия {{---}} Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006/algorithm Алгоритм]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38961</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38961"/>
				<updated>2014-06-13T07:31:17Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Смотри также */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&lt;br /&gt;
Рассмотрим данный алгоритм на определенных глубинах рекурсии (то есть на разных уровнях дерева):&lt;br /&gt;
&lt;br /&gt;
* На глубине 0. (на рисунке глубина обозначена слева от уровня). Текущий полуинтервал &amp;lt;tex&amp;gt;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 1. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 2. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 3. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи RSQ.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; sum&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' get_sum ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' 0&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].sum&lt;br /&gt;
        '''return''' get_sum (node * 2 + 1, a, b) + get_sum (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83 Реализация запроса в дереве отрезков снизу]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38960</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38960"/>
				<updated>2014-06-13T07:30:49Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&lt;br /&gt;
Рассмотрим данный алгоритм на определенных глубинах рекурсии (то есть на разных уровнях дерева):&lt;br /&gt;
&lt;br /&gt;
* На глубине 0. (на рисунке глубина обозначена слева от уровня). Текущий полуинтервал &amp;lt;tex&amp;gt;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 1. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 2. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 3. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи RSQ.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; sum&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' get_sum ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' 0&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].sum&lt;br /&gt;
        '''return''' get_sum (node * 2 + 1, a, b) + get_sum (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
==Смотри также==&lt;br /&gt;
* [http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%BD%D0%B8%D0%B7%D1%83 Реализация запроса в дереве отрезков снизу]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38959</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38959"/>
				<updated>2014-06-13T07:28:20Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Ссылки */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&lt;br /&gt;
Рассмотрим данный алгоритм на определенных глубинах рекурсии (то есть на разных уровнях дерева):&lt;br /&gt;
&lt;br /&gt;
* На глубине 0. (на рисунке глубина обозначена слева от уровня). Текущий полуинтервал &amp;lt;tex&amp;gt;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 1. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 2. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 3. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи RSQ.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; sum&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' get_sum ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' 0&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].sum&lt;br /&gt;
        '''return''' get_sum (node * 2 + 1, a, b) + get_sum (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38958</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38958"/>
				<updated>2014-06-13T07:26:22Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая {{---}} нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&lt;br /&gt;
Рассмотрим данный алгоритм на определенных глубинах рекурсии (то есть на разных уровнях дерева):&lt;br /&gt;
&lt;br /&gt;
* На глубине 0. (на рисунке глубина обозначена слева от уровня). Текущий полуинтервал &amp;lt;tex&amp;gt;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 1. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 2. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 3. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи RSQ.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; sum&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' get_sum ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' 0&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].sum&lt;br /&gt;
        '''return''' get_sum (node * 2 + 1, a, b) + get_sum (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38957</id>
		<title>Реализация запроса в дереве отрезков сверху</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%B0_%D0%B2_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%B5_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2_%D1%81%D0%B2%D0%B5%D1%80%D1%85%D1%83&amp;diff=38957"/>
				<updated>2014-06-13T07:24:28Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Данная операция позволяет выполнять запросы на [[Дерево отрезков. Построение|дереве отрезков]], причем алгоритм запускается от корня и рекурсивно идет сверху вниз.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
''Замечание.''&lt;br /&gt;
Используем в алгоритме не отрезки, а полуинтервалы (левая граница включительно, а правая - нет).&lt;br /&gt;
&lt;br /&gt;
Пусть есть уже [[Дерево отрезков. Построение|построенное дерево отрезков]]  и идет запрос на полуинтервале &amp;lt;tex&amp;gt;[a .. b)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве параметров рекурсий передаем следующие переменные:&lt;br /&gt;
* &amp;lt;tex&amp;gt;node&amp;lt;/tex&amp;gt; {{---}} номер (в массиве с деревом отрезков) текущей вершины дерева.&lt;br /&gt;
* &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt;  {{---}} левая и правая границы запрашиваемого полуинтервала.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; {{---}} это левая и правая границы полуинтервала, за которые &amp;quot;отвечает&amp;quot; наша вершина.&lt;br /&gt;
Запустим рекурсивную процедуру от всего полуинтервала  (то есть от корневой вершины).&lt;br /&gt;
&lt;br /&gt;
Для текущего состояния проверяем следующие условия :&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал не пересекается с искомым, то возвращаем нейтральный элемент.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[1..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[3 .. 5)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Если текущий полуинтервал лежит внутри запрашиваемого полуинтервала, то возвращаем значение в текущей вершине.&lt;br /&gt;
:''Например'': текущий &amp;lt;tex&amp;gt;[2..3)&amp;lt;/tex&amp;gt;, а искомый &amp;lt;tex&amp;gt;[2..4)&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* Иначе переходим к рекурсивным вызовам функций от детей вершины. При этом возвращаем значение на текущем полуинтервале, как функцию (соответствующую типу нашего запроса) от результатов выполнения на детях.&lt;br /&gt;
&lt;br /&gt;
Так как на каждом уровне дерева рекурсия может дойти до не более, чем двух вершин (иначе бы нашлось две рядом стоящие вершины одного уровня, объединение которых дало отрезок, за который отвечает вершина предыдущего уровня), а всего уровней &amp;lt;tex&amp;gt;\log 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;
Рассмотрим данный алгоритм на примере задачи RSQ (Range Sum Query {{---}} запрос суммы на отрезке).&lt;br /&gt;
&lt;br /&gt;
При этом сумма на текущем полуинтервале (в случае вызова рекурсий от детей) равна сумме результатов выполнения операции на этих детях.&lt;br /&gt;
&lt;br /&gt;
Пусть дерево содержит &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; листьев и запрашиваемая сумма &lt;br /&gt;
{{---}} это отрезок &amp;lt;tex&amp;gt;[1 .. 4]&amp;lt;/tex&amp;gt; (полуинтервал &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt;).&lt;br /&gt;
[[Файл:Image_4.png|right|602px|Пример рабoты алгоритма]]&lt;br /&gt;
Рассмотрим данный алгоритм на определенных глубинах рекурсии (то есть на разных уровнях дерева):&lt;br /&gt;
&lt;br /&gt;
* На глубине 0. (на рисунке глубина обозначена слева от уровня). Текущий полуинтервал &amp;lt;tex&amp;gt;[0 .. 8)&amp;lt;/tex&amp;gt; пересекается с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow&amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 1. &amp;lt;tex&amp;gt;[0 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 8)&amp;lt;/tex&amp;gt; пересекаются с &amp;lt;tex&amp;gt; [1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим по рекурсивным вызовам на полуинтервалах &amp;lt;tex&amp;gt;[0 ..&lt;br /&gt;
 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 2. &lt;br /&gt;
** &amp;lt;tex&amp;gt;[0 .. 2)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 6)&amp;lt;/tex&amp;gt; пересекаются с  &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; переходим в листья &amp;lt;tex&amp;gt;0, 1, 4, 5 &amp;lt;/tex&amp;gt;&lt;br /&gt;
** &amp;lt;tex&amp;gt;[2 .. 4) &amp;lt;/tex&amp;gt; полностью лежит внутри &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем сумму на этом отрезке&lt;br /&gt;
** &amp;lt;tex&amp;gt;[6 .. 8)&amp;lt;/tex&amp;gt; не пересекается с &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* На глубине 3. &lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;1, 4&amp;lt;/tex&amp;gt; лежат в запрашиваемом интервале &amp;lt;tex&amp;gt;\Rightarrow &amp;lt;/tex&amp;gt; возвращаем значения в них&lt;br /&gt;
** Листья &amp;lt;tex&amp;gt;0, 5&amp;lt;/tex&amp;gt; лежат вне &amp;lt;tex&amp;gt;[1 .. 5) \Rightarrow &amp;lt;/tex&amp;gt; возвращаем нулевое значение&lt;br /&gt;
&lt;br /&gt;
Таким образом ответ на полуинтервале &amp;lt;tex&amp;gt;[1 .. 5)&amp;lt;/tex&amp;gt; равен сумме значений в вершинах, отвечающих за полуинтервалы &amp;lt;tex&amp;gt;[1 .. 2)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;[2 .. 4)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[4 .. 5)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Реализация==&lt;br /&gt;
Рассмотрим реализацию задачи RSQ.&lt;br /&gt;
&lt;br /&gt;
Пусть в узлах дерева хранятся структуры из трех полей:&lt;br /&gt;
* &amp;lt;tex&amp;gt;left&amp;lt;/tex&amp;gt; {{---}} левая граница полуинтервала, за который &amp;quot;отвечает&amp;quot; текущая вершина.&lt;br /&gt;
* &amp;lt;tex&amp;gt;right&amp;lt;/tex&amp;gt; {{---}} правая граница этого полуинтервала.&lt;br /&gt;
* &amp;lt;tex&amp;gt; sum&amp;lt;/tex&amp;gt; {{---}} сумма на полуинтервале.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  '''int''' get_sum ('''int''' node, '''int''' a, '''int''' b)     &lt;br /&gt;
        l = tree[node].left&lt;br /&gt;
        r = tree[node].right &lt;br /&gt;
        '''if'''  [l, r) &amp;lt;tex&amp;gt;\cap &amp;lt;/tex&amp;gt; [a, b) == &amp;lt;tex&amp;gt; \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''return''' 0&lt;br /&gt;
        '''if''' [l, r) &amp;lt;tex&amp;gt;\subset&amp;lt;/tex&amp;gt; [a, b)&lt;br /&gt;
            '''return''' tree[node].sum&lt;br /&gt;
        '''return''' get_sum (node * 2 + 1, a, b) + get_sum (node * 2 + 2, a, b)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[http://e-maxx.ru/algo/segment_tree MAXimal :: algo :: Дерево отрезков]&lt;br /&gt;
&lt;br /&gt;
[http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%BE%D1%82%D1%80%D0%B5%D0%B7%D0%BA%D0%BE%D0%B2  Дерево отрезков — Википедия]&lt;br /&gt;
&lt;br /&gt;
[http://rain.ifmo.ru/cat/view.php/vis/trees/segment-2006 Визуализатор дерева отрезков]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Дерево отрезков]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38956</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38956"/>
				<updated>2014-06-13T07:12:54Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''srtruct''' nameOfStruct &lt;br /&gt;
     int head&lt;br /&gt;
     *nameOfStruct next&lt;br /&gt;
     int data&lt;br /&gt;
&lt;br /&gt;
 nameOFStruct s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(nameOfStruct x):                   &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union(nameOfStruct x, nameOfStruct y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y                         &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail                         &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null                         &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38955</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38955"/>
				<updated>2014-06-13T07:07:55Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''srtruct''' nameOfStruct &lt;br /&gt;
     int head&lt;br /&gt;
     *nameOfStruct next&lt;br /&gt;
     int data&lt;br /&gt;
&lt;br /&gt;
 nameOFStruct s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(nameOfStruct x):               &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union(nameOfStruct x, nameOfStruct y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y       &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail       &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null       &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38954</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38954"/>
				<updated>2014-06-13T07:07:03Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''srtruct''' nameOfStruct &lt;br /&gt;
     int head&lt;br /&gt;
     *nameOfStruct next&lt;br /&gt;
     int data&lt;br /&gt;
&lt;br /&gt;
 nameOFStruct s[n]&lt;br /&gt;
&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x):               &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union(nameOfStruct x, nameOfStruct y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y       &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail       &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null       &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38742</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38742"/>
				<updated>2014-06-12T07:12:48Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Структура */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left ( T_{min}, PQ \right) = \langle T_{min}, PQ \left (BPQ \left \langle T_{min}, PQ\right \rangle \right)\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, BPQ&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''BPQ'''):&lt;br /&gt;
     '''return''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''return''' x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди, состоящей из &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, BPQ&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' extractMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, t&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt; = extractMin(q)&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, merge(r, t)&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38741</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38741"/>
				<updated>2014-06-12T06:38:29Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|center|Пример работы СНМ]]&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x):               &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y       &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail       &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null       &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|center|Пример объединения двух множеств (union)]]&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38740</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38740"/>
				<updated>2014-06-12T06:15:51Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, BPQ&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''BPQ'''):&lt;br /&gt;
     '''return''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''return''' x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди, состоящей из &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, BPQ&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' extractMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, t&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt; = extractMin(q)&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, merge(r, t)&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38739</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38739"/>
				<updated>2014-06-12T05:03:23Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Insert */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''bpq'''):&lt;br /&gt;
     '''return''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''return''' x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди, состоящей из &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' extractMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, t&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt; = extractMin(q)&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, merge(r, t)&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38738</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38738"/>
				<updated>2014-06-12T05:02:56Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* getMin */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''bpq'''):&lt;br /&gt;
     return merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''return''' x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди, состоящей из &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' extractMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, t&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt; = extractMin(q)&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, merge(r, t)&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38737</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38737"/>
				<updated>2014-06-12T04:49:58Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Merge */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''bpq'''):&lt;br /&gt;
     return merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     return x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди, состоящей из &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' extractMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, t&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt; = extractMin(q)&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, merge(r, t)&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38736</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38736"/>
				<updated>2014-06-12T04:46:17Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* extractMin */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x : '''int''', q : '''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;:'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''bpq'''):&lt;br /&gt;
     return merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     return x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди, состоящей из &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' extractMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, t&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt; = extractMin(q)&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, merge(r, t)&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38735</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38735"/>
				<updated>2014-06-12T04:20:36Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* getMin */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x : '''int''', q : '''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;:'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''bpq'''):&lt;br /&gt;
     return merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;):&lt;br /&gt;
     return x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     ((y, r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38734</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38734"/>
				<updated>2014-06-12T04:19:40Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Insert */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x : '''int''', q : '''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;:'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;int, bpq&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;''' insert(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x:'''int''', q:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, y:'''bpq'''):&lt;br /&gt;
     return merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     return x;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     ((y, r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38733</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38733"/>
				<updated>2014-06-12T04:13:58Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Merge */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x : '''int''', q : '''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y:'''int''', r:'''bpq'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;:'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;y, r&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, &amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x, q&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' insert((x:'''int''', q:'''bpq'''):'''pair''', y:'''bpq'''):&lt;br /&gt;
     return merge((x, q), create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     return x;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     ((y, r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38732</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38732"/>
				<updated>2014-06-12T04:09:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x : '''int''', q : '''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, (y:'''int''', r:'''bpq'''):'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, (y, r)))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, (x, q)))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' insert((x:'''int''', q:'''bpq'''):'''pair''', y:'''bpq'''):&lt;br /&gt;
     return merge((x, q), create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     return x;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди &amp;lt;tex&amp;gt; BPQ&amp;lt;/tex&amp;gt;ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     ((y, r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt; и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем &amp;lt;tex&amp;gt; BPQ &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38731</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38731"/>
				<updated>2014-06-12T03:41:45Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, добавлении минимального элемента и  на идеи Data-structural bootstrapping. Первое позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, второе позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, а  третье {{---}} позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго ''BPQ''.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''BPQ''' merge(&amp;lt;tex&amp;gt; \langle &amp;lt;/tex&amp;gt;x : '''int''', q : '''BPQ'''&amp;lt;tex&amp;gt; \rangle &amp;lt;/tex&amp;gt;, (y:'''int''', r:'''bpq'''):'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, (y, r)))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, (x, q)))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового ''BPQ'' и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' insert((x:'''int''', q:'''bpq'''):'''pair''', y:'''bpq'''):&lt;br /&gt;
     return merge((x, q), create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как ''BPQ'' хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     return x;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем ''BPQ'', по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди ''BPQ'''ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     ((y, r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа ''BPQ'' из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа ''BPQ'' и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем ''BPQ'', где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38549</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38549"/>
				<updated>2014-06-11T09:08:42Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Операции */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, что позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, добавлении минимального элемента, позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, и идеи Data-structural bootstrapping, позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго ''BPQ''.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' merge((x:'''int''', q:'''bpq'''):'''pair''', (y:'''int''', r:'''bpq'''):'''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, (y, r)))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, (x, q)))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового ''BPQ'' и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' insert((x:'''int''', q:'''bpq'''):'''pair''', y:'''bpq'''):&lt;br /&gt;
     return merge((x, q), create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как ''BPQ'' хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     return x;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем ''BPQ'', по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди ''BPQ'''ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin((x:'''int''', q:'''bpq'''):'''pair'''):&lt;br /&gt;
     ((y, r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа ''BPQ'' из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа ''BPQ'' и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем ''BPQ'', где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38547</id>
		<title>Куча Бродала-Окасаки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%83%D1%87%D0%B0_%D0%91%D1%80%D0%BE%D0%B4%D0%B0%D0%BB%D0%B0-%D0%9E%D0%BA%D0%B0%D1%81%D0%B0%D0%BA%D0%B8&amp;diff=38547"/>
				<updated>2014-06-11T08:52:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Куча Бродала-Окасаки''' (англ. ''Brodal's and Okasaki's Priority Queue'') {{---}} основана на использовании [[Биномиальная куча|биномиальной кучи]] без каскадных ссылок, что позволяет делать &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, добавлении минимального элемента, позволяет получать минимальный элемент за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, и идеи Data-structural bootstrapping, позволяющей выполнить &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt;  за &amp;lt;tex&amp;gt;O(1)&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;
Используем идею, которую Тарьян и Буксбаум называют Data-structural bootstrapping. &lt;br /&gt;
{{Определение&lt;br /&gt;
|neat = 0&lt;br /&gt;
|definition= '''Data-structural bootstrapping''' {{---}} это идея, позволяющая снизить время &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; до &amp;lt;tex&amp;gt;O(1)&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;
Создадим структуру Bootstrapping Priority Queues, которая будет хранить пару из минимального элемента &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и приоритетную очередь. Элементами приоритетной очереди будут Bootstrapping Priority Queues упорядоченные по &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt;. Это можно записать так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; BPQ \left \langle T_{min}, PQ \right \rangle = (T_{min}, PQ \left \langle BPQ \left \langle T_{min}, PQ\right \rangle \right \rangle)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Куча из одного элемента будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \mathrm{create} &amp;lt;/math&amp;gt;&amp;lt;tex&amp;gt;(x) = BPQ \left \langle x, null\right \rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная структура не будет бесконечной, так как каждый раз в приоритетной очереди будет храниться на один элемент меньше, таким образом образуя иерархическую структуру. Каждое значение храниться в одном из значений &amp;lt;tex&amp;gt;T_{min}.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
=== Merge ===&lt;br /&gt;
Слияние выполняется выбором минимума из двух значений &amp;lt;tex&amp;gt;T_{min}&amp;lt;/tex&amp;gt; и добавлением в приоритетную очередь второго BPQ.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' merge((x : '''int''', q : '''bpq''') : '''pair''', (y : '''int''', r : '''bpq''') : '''pair'''):&lt;br /&gt;
     '''if''' x &amp;lt; y&lt;br /&gt;
         '''return''' (x, insert(q, (y, r)))&lt;br /&gt;
     '''else'''&lt;br /&gt;
         '''return''' (y, insert(r, (x, q)))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; это добавление в приоритетную очередь работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Insert ===&lt;br /&gt;
Это создание нового BPQ и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; его с основным деревом.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair(int, bpq)''' insert((x : '''int''', q : '''bpq'''), y : '''bpq'''):&lt;br /&gt;
     return merge((x,q), create(y))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Создание и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{insert}&amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== getMin ===&lt;br /&gt;
Выполняется просто, так как BPQ хранит минимум.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' getMin((x : '''int''', q : '''bpq''')):&lt;br /&gt;
     return x;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Очевидно, работает за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== extractMin ===&lt;br /&gt;
Минимальный элемент хранится в верхнем BPQ, по этому его поиск не нужен. Требуется извлечение минимума из приоритетной очереди BPQ'ов. &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''pair (int, bpq)''' extractMin('''pair'''(x : '''int''', q : '''bpq''')):&lt;br /&gt;
     ((y,r), t) = extractMin(q)&lt;br /&gt;
     '''return''' (y, merge(r, t))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt;{{---}} это функция, извлекающая минимальный элемент типа BPQ из приоритетной очереди, она возвращает &amp;lt;tex&amp;gt;(y,r)&amp;lt;/tex&amp;gt; {{---}} минимальный элемент типа BPQ и остаток от приоритетной очереди после извлечение минимума {{---}} &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;. &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; функция, выполняющая слияние двух приоритетных очередей.&lt;br /&gt;
&lt;br /&gt;
Возвращаем BPQ, где &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} новый минимальный элемент, и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; приоритетная очередь без элемента &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathrm{merge}&amp;lt;/math&amp;gt; выполняются за &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, тогда &amp;lt;math&amp;gt;\mathrm{extractMin}&amp;lt;/math&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;
* [[Очередь]]&lt;br /&gt;
* [[Персистентная очередь]]&lt;br /&gt;
* [[Персистентная приоритетная очередь]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://www.lektorium.tv/lecture/?id=14234 Лекция А.С. Станкевича по приоритетным очередям]&lt;br /&gt;
&lt;br /&gt;
* [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973 Optimal Purely Functional Priority Queues]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Приоритетные очереди]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38536</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38536"/>
				<updated>2014-06-11T07:44:32Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью массива */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x):               &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y       &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail       &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null       &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38535</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38535"/>
				<updated>2014-06-11T07:39:08Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;. Тогда union работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x):               &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     x.tail.next = y       &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail       &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null       &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38534</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38534"/>
				<updated>2014-06-11T07:35:12Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;. Тогда union работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x): &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail.next = y&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38533</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38533"/>
				<updated>2014-06-11T07:34:41Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* Описание */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;. Тогда union работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x): &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail.next = y&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|thumb|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38532</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38532"/>
				<updated>2014-06-11T07:33:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|thumb|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;. Тогда union работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x): &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail.next = y&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|thumb|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38531</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38531"/>
				<updated>2014-06-11T07:30:17Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью списка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|thumb|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;. Тогда union работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Значит &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt;. Таким образом, &amp;lt;math&amp;gt; \mathrm{union} &amp;lt;/math&amp;gt; работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt;. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' find(x): &amp;lt;font color=green&amp;gt; // подразумевается, что &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; {{ --- }} ссылка на один из элементов &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x.head.data&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''func''' union('''int''' x, '''int''' y): &amp;lt;font color=green&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;/font&amp;gt;&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     '''if''' x == y&lt;br /&gt;
         '''return'''&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // соединим списки &amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail.next = y&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // сделаем корректную ссылку на &amp;lt;tex&amp;gt; tail &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; head&amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
     x.tail = y.tail&lt;br /&gt;
     &amp;lt;font color=green&amp;gt; // скорректируем ссылки на &amp;lt;tex&amp;gt; head &amp;lt;/tex&amp;gt; у элементов множества &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; &amp;lt;/font&amp;gt;&lt;br /&gt;
     '''while''' y &amp;lt;tex&amp;gt; \neq &amp;lt;/tex&amp;gt; null&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|thumb|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38525</id>
		<title>СНМ (наивные реализации)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%9D%D0%9C_(%D0%BD%D0%B0%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8)&amp;diff=38525"/>
				<updated>2014-06-11T07:10:57Z</updated>
		
		<summary type="html">&lt;p&gt;Nastya: /* С помощью массива */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Система (лес, объединение) непересекающихся множеств''' (СНМ, disjoint set forest, DSF, disjoint set union, DSU) {{---}} иерархическая структура данных, позволяющая эффективно работать с множествами. &lt;br /&gt;
__TOC__&lt;br /&gt;
== Описание ==&lt;br /&gt;
Структура хранит набор объектов (например, чисел от &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; n - 1 &amp;lt;/tex&amp;gt;) в виде непересекающихся множеств. У каждого множества есть конкретный представитель.&lt;br /&gt;
&lt;br /&gt;
Определены две операции:&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{union(x, y)} &amp;lt;/math&amp;gt; {{ --- }} объединяет множества, содержащие &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; {{ --- }} возвращает представителя множества, в котором находится &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;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;math&amp;gt; \mathrm{find (x)} &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; \mathrm{find(y)} &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_1_Example.png|500px|left|thumb|Пример работы СНМ]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Реализации ==&lt;br /&gt;
=== С помощью массива ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть в массиве s хранятся номера множеств, в &amp;lt;tex&amp;gt; s[i] &amp;lt;/tex&amp;gt; будет храниться номер множества, к которому принадлежит &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Этот номер отождествляет множество, &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt; возвращает именно его. Тогда &amp;lt;math&amp;gt; \mathrm{find} &amp;lt;/math&amp;gt;, очевидно, будет работать за &amp;lt;tex&amp;gt;O(1)&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; s[i] &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;. Тогда union работает за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int''' s[n]&lt;br /&gt;
 '''func''' init():&lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         s[i] = i               &amp;lt;font color=green&amp;gt; // сначала каждый элемент лежит в своем множестве &amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''int''' find(k):&lt;br /&gt;
     '''return''' s[k]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''func''' union(x, y):&lt;br /&gt;
     '''if''' s[x] == s[y]&lt;br /&gt;
         '''return'''&lt;br /&gt;
     '''else'''&lt;br /&gt;
         t = s[y]&lt;br /&gt;
         '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
             '''if''' s[i] == t&lt;br /&gt;
                 s[i] = s[x]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== С помощью списка ===&lt;br /&gt;
&amp;lt;!--'''Оценка работы:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
 |init&lt;br /&gt;
 |find&lt;br /&gt;
 |union&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;tex&amp;gt;O(n)&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;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;&lt;br /&gt;
 |}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем хранить множество в виде списка. Для каждого элемента списка храним ссылку на следующий элемент и указатель на head, который является представителем. Для того чтобы найти представителя, нужно перейти по ссылке на head. Значит find работает за &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для объединения множеств потребуется объединить два списка и обновить ссылки на head. Таким образом, union работает за &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Чтобы объединить два списка, нужно хранить ссылку на tail. Ее можно хранить в голове списка.&lt;br /&gt;
&lt;br /&gt;
 s[n]&lt;br /&gt;
 init():&lt;br /&gt;
     for i = 0 to n - 1:&lt;br /&gt;
         s[i].data = i&lt;br /&gt;
         s[i].next = null&lt;br /&gt;
         s[i].head = s[i]&lt;br /&gt;
 &lt;br /&gt;
 find(x): // подразумевается, что x {{ --- }} ссылка на один из элементов&lt;br /&gt;
     return x.head.data&lt;br /&gt;
 &lt;br /&gt;
 union(x, y): // x и y {{ --- }} элементы множеств&lt;br /&gt;
     x = x.head&lt;br /&gt;
     y = y.head&lt;br /&gt;
     if x == y:&lt;br /&gt;
         return&lt;br /&gt;
     // соединим списки&lt;br /&gt;
     x.tail.next = y&lt;br /&gt;
     // сделаем корректную ссылку на tail в head&lt;br /&gt;
     x.tail = y.tail&lt;br /&gt;
     // скорректируем ссылки на head у элементов множества &amp;quot;y&amp;quot;&lt;br /&gt;
     while y != null:&lt;br /&gt;
         y.head = x&lt;br /&gt;
         y = y.next&lt;br /&gt;
&lt;br /&gt;
[[Файл:DSU_list_example.png|800px|left|thumb|Пример объединения двух множеств (union)]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие реализации ==&lt;br /&gt;
* [[СНМ (списки с весовой эвристикой)]]&lt;br /&gt;
* [[СНМ (реализация с помощью леса корневых деревьев)]]&lt;br /&gt;
&lt;br /&gt;
== Источники ==&lt;br /&gt;
* Т. Кормен - Алгоритмы, построение и анализ. Второе издание. Часть V. Глава 21.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://habrahabr.ru/blogs/algorithm/104772/ Система непересекающихся множеств и её применения]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;/div&gt;</summary>
		<author><name>Nastya</name></author>	</entry>

	</feed>