<?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=94.25.177.20&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=94.25.177.20&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/94.25.177.20"/>
		<updated>2026-04-11T11:43:52Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D0%BA%D0%B0%D1%80%D1%82%D0%BE%D0%B2%D0%BE_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=78583</id>
		<title>Декартово дерево</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D0%BA%D0%B0%D1%80%D1%82%D0%BE%D0%B2%D0%BE_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=78583"/>
				<updated>2021-01-15T13:08:22Z</updated>
		
		<summary type="html">&lt;p&gt;94.25.177.20: /* Другой алгоритм за O(n\log n) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Эта статья про курево''&lt;br /&gt;
&lt;br /&gt;
'''Декартово дерево или дерамида''' (англ. ''Treap'') {{---}} это структура данных, объединяющая в себе [[Дерево поиска, наивная реализация|бинарное дерево поиска]] и [[Двоичная куча|бинарную кучу]] (отсюда и второе её название: treap (tree + heap) и дерамида (дерево + пирамида), также существует название курево (куча + дерево).&lt;br /&gt;
&lt;br /&gt;
Более строго, это бинарное дерево, в узлах которого хранятся пары &amp;lt;tex&amp;gt; (x,y) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} это ключ, а &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; {{---}} это приоритет. Также оно является двоичным деревом поиска по &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и пирамидой по &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;. Предполагая, что все &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и все &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; являются различными, получаем, что если некоторый элемент дерева содержит &amp;lt;tex&amp;gt;(x_0,y_0)&amp;lt;/tex&amp;gt;, то у всех элементов в левом поддереве &amp;lt;tex&amp;gt;x &amp;lt; x_0&amp;lt;/tex&amp;gt;, у всех элементов в правом поддереве &amp;lt;tex&amp;gt; x &amp;gt; x_0&amp;lt;/tex&amp;gt;, а также и в левом, и в правом поддереве имеем: &amp;lt;tex&amp;gt; y &amp;lt; y_0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Дерамиды были предложены Сиделем (Siedel) и Арагон (Aragon) в 1996 г.&lt;br /&gt;
&lt;br /&gt;
== Операции в декартовом дереве ==&lt;br /&gt;
=== split ===&lt;br /&gt;
[[file:split.png|thumb|400px|Операция split]]&lt;br /&gt;
&lt;br /&gt;
Операция &amp;lt;tex&amp;gt;\mathrm{split}&amp;lt;/tex&amp;gt; (''разрезать'') позволяет сделать следующее: разрезать исходное дерево &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; по ключу &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. Возвращать она будет такую пару деревьев &amp;lt;tex&amp;gt;\langle T_1, T_2\rangle &amp;lt;/tex&amp;gt;, что в дереве &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; ключи меньше &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, а в дереве &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt; все остальные:  &amp;lt;tex&amp;gt;\mathrm{split}(T, k) \to \langle T_1, T_2\rangle &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Эта операция устроена следующим образом.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим случай, в котором требуется разрезать дерево по ключу, большему ключа корня.&lt;br /&gt;
Посмотрим, как будут устроены результирующие деревья &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt;:&lt;br /&gt;
* &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt;: левое поддерево &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; совпадёт с левым поддеревом &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Для нахождения правого поддерева &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt;, нужно разрезать правое поддерево &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;T^R_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T^R_2&amp;lt;/tex&amp;gt; по ключу &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; и взять &amp;lt;tex&amp;gt;T^R_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt; совпадёт с &amp;lt;tex&amp;gt;T^R_2&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;\langle&amp;lt;/tex&amp;gt;Treap, Treap&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;''' split(t: '''Treap''', k: '''int'''):&lt;br /&gt;
   '''if''' t == &amp;lt;tex&amp;gt; \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\langle&amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt; \varnothing &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \varnothing &amp;lt;/tex&amp;gt;&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;     &lt;br /&gt;
   '''else if''' k &amp;gt; t.x &lt;br /&gt;
     &amp;lt;tex&amp;gt;\langle&amp;lt;/tex&amp;gt;t1, t2&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt; = split(t.right, k)&lt;br /&gt;
     t.right = t1&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\langle&amp;lt;/tex&amp;gt;t, t2&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
   '''else''' &lt;br /&gt;
     &amp;lt;tex&amp;gt;\langle&amp;lt;/tex&amp;gt;t1, t2&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt; = split(t.left, k)&lt;br /&gt;
     t.left = t2&lt;br /&gt;
     '''return''' &amp;lt;tex&amp;gt;\langle&amp;lt;/tex&amp;gt;t1, t&amp;lt;tex&amp;gt;\rangle&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
&lt;br /&gt;
Оценим время работы операции &amp;lt;tex&amp;gt;\mathrm{split}&amp;lt;/tex&amp;gt;. Во время выполнения вызывается одна операция &amp;lt;tex&amp;gt;\mathrm{split}&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(h)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; {{---}} высота дерева.&lt;br /&gt;
&lt;br /&gt;
=== merge ===&lt;br /&gt;
[[file:merge.png|thumb|400px|Операция merge]]&lt;br /&gt;
&lt;br /&gt;
Рассмотрим вторую операцию с декартовыми деревьями {{---}} &amp;lt;tex&amp;gt;\mathrm{merge}&amp;lt;/tex&amp;gt; (''слить''). &lt;br /&gt;
&lt;br /&gt;
С помощью этой операции можно слить два декартовых дерева в одно.&lt;br /&gt;
Причём, все ключи в первом(''левом'') дереве должны быть меньше, чем&lt;br /&gt;
ключи во втором(''правом''). В результате получается дерево, в котором есть все ключи из первого и второго деревьев:  &amp;lt;tex&amp;gt;\mathrm{merge}(T_1, T_2) \to \{T\}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим принцип работы этой операции. Пусть нужно слить деревья &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда, очевидно, у результирующего дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; есть корень. &lt;br /&gt;
Корнем станет вершина из &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt; с наибольшим приоритетом &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;. Но вершина с самым большим &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; из всех вершин деревьев &lt;br /&gt;
&amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt; может быть только либо корнем &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt;, либо корнем &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Рассмотрим случай, в котором корень &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; имеет больший &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, чем корень &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Случай, в котором корень &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt; имеет больший &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;, чем корень &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt;, симметричен этому.&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; корня &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; больше &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; корня &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt;, то он и будет являться корнем. Тогда левое поддерево &lt;br /&gt;
&amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; совпадёт с левым поддеревом &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt;. Справа же нужно подвесить объединение правого поддерева&lt;br /&gt;
&amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; и дерева &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&lt;br /&gt;
 '''Treap''' merge(t1: '''Treap''', t2: '''Treap'''):&lt;br /&gt;
   '''if''' t2 == &amp;lt;tex&amp;gt; \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' t1&lt;br /&gt;
   '''if''' t1 == &amp;lt;tex&amp;gt; \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     '''return''' t2&lt;br /&gt;
   '''else if''' t1.y &amp;gt; t2.y&lt;br /&gt;
     t1.right = merge(t1.right, t2)&lt;br /&gt;
     '''return''' t1&lt;br /&gt;
   '''else''' &lt;br /&gt;
     t2.left = merge(t1, t2.left)&lt;br /&gt;
     '''return''' t2&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
&lt;br /&gt;
Рассуждая аналогично операции &amp;lt;tex&amp;gt;\mathrm{split}&amp;lt;/tex&amp;gt;, приходим к выводу, что трудоёмкость операции &amp;lt;tex&amp;gt;\mathrm{merge}&amp;lt;/tex&amp;gt; &lt;br /&gt;
равна &amp;lt;tex&amp;gt;O(h)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; {{---}} высота дерева.&lt;br /&gt;
&lt;br /&gt;
=== insert ===&lt;br /&gt;
Операция &amp;lt;tex&amp;gt;\mathrm{insert}(T, k)&amp;lt;/tex&amp;gt; добавляет в дерево &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; элемент &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;k.x&amp;lt;/tex&amp;gt; {{---}} ключ, а &amp;lt;tex&amp;gt;k.y&amp;lt;/tex&amp;gt; {{---}} приоритет.&lt;br /&gt;
&lt;br /&gt;
Представим что элемент &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, это декартово дерево из одного элемента, и для того чтобы его добавить в наше декартово дерево &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;, очевидно, нам нужно их слить. Но &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; может содержать ключи как меньше, так и больше ключа &amp;lt;tex&amp;gt;k.x&amp;lt;/tex&amp;gt;, поэтому сначала нужно разрезать &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; по ключу &amp;lt;tex&amp;gt;k.x&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Реализация №1 &lt;br /&gt;
# Разобьём наше дерево по ключу, который мы хотим добавить, то есть &amp;lt;tex&amp;gt;\mathrm{split}(T, k.x) \to \langle T_1, T_2\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Сливаем первое дерево с новым элементом, то есть &amp;lt;tex&amp;gt;\mathrm{merge}(T_1, k) \to T_1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Сливаем получившиеся дерево со вторым, то есть &amp;lt;tex&amp;gt;\mathrm{merge}(T_1, T_2) \to T&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Реализация №2  &lt;br /&gt;
# Сначала спускаемся по дереву (как в обычном бинарном дереве поиска по &amp;lt;tex&amp;gt;k.x&amp;lt;/tex&amp;gt;), но останавливаемся на первом элементе, в котором значение приоритета оказалось меньше &amp;lt;tex&amp;gt;k.y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Теперь вызываем &amp;lt;tex&amp;gt;\mathrm{split}(T, k.x) \to \langle T_1, T_2\rangle&amp;lt;/tex&amp;gt; от найденного элемента (от элемента вместе со всем его поддеревом) &lt;br /&gt;
# Полученные &amp;lt;tex&amp;gt;T_1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;T_2&amp;lt;/tex&amp;gt; записываем в качестве левого и правого сына добавляемого элемента.&lt;br /&gt;
# Полученное дерево ставим на место элемента, найденного в первом пункте.&lt;br /&gt;
&lt;br /&gt;
В первой реализации два раза используется &amp;lt;tex&amp;gt;\mathrm{merge}&amp;lt;/tex&amp;gt;, а во второй реализации слияние вообще не используется.&lt;br /&gt;
&lt;br /&gt;
=== remove ===&lt;br /&gt;
Операция &amp;lt;tex&amp;gt;\mathrm{remove}(T, x)&amp;lt;/tex&amp;gt; удаляет из дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; элемент с ключом &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Реализация №1&lt;br /&gt;
&lt;br /&gt;
# Разобьём наше дерево по ключу, который мы хотим удалить, то есть &amp;lt;tex&amp;gt;\mathrm{split }(T, k.x) \to \langle T_1, T_2\rangle&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Теперь отделяем от первого дерева элемент &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, то есть самого левого ребёнка дерева &amp;lt;tex&amp;gt; T_2 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Сливаем первое дерево со вторым, то есть &amp;lt;tex&amp;gt;\mathrm{merge }(T_1, T_2) \to T&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
* Реализация №2&lt;br /&gt;
# Спускаемся по дереву (как в обычном бинарном дереве поиска по &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;), и ищем удаляемый элемент. &lt;br /&gt;
# Найдя элемент, вызываем &amp;lt;tex&amp;gt;\mathrm{merge}&amp;lt;/tex&amp;gt; его левого и правого сыновей&lt;br /&gt;
# Результат процедуры &amp;lt;tex&amp;gt;\mathrm{merge}&amp;lt;/tex&amp;gt; ставим на место удаляемого элемента.&lt;br /&gt;
&lt;br /&gt;
В первой реализации один раз используется &amp;lt;tex&amp;gt;\mathrm{split}&amp;lt;/tex&amp;gt;, а во второй реализации разрезание вообще не используется.&lt;br /&gt;
&lt;br /&gt;
== Построение декартова дерева ==&lt;br /&gt;
Пусть нам известно из каких пар &amp;lt;tex&amp;gt;(x_i, y_i)&amp;lt;/tex&amp;gt; требуется построить декартово дерево, причём также известно, что &amp;lt;tex&amp;gt;x_1 &amp;lt; x_2 &amp;lt; \ldots &amp;lt; x_n&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Алгоритм за &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt; ===&lt;br /&gt;
Отсортируем все приоритеты по убыванию за &amp;lt;tex&amp;gt; O(n\log n) &amp;lt;/tex&amp;gt; и выберем первый из них, пусть это будет &amp;lt;tex&amp;gt;y_k&amp;lt;/tex&amp;gt;. Сделаем &amp;lt;tex&amp;gt;(x_k, y_k)&amp;lt;/tex&amp;gt; корнем дерева. Проделав то же самое с остальными вершинами получим левого и правого сына &amp;lt;tex&amp;gt;(x_k, y_k)&amp;lt;/tex&amp;gt;. В среднем высота Декартова дерева &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;  (см. далее) и на каждом уровне мы сделали &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; операций. Значит такой алгоритм работает за &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Другой алгоритм за &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt; ===&lt;br /&gt;
Отсортируем пары &amp;lt;tex&amp;gt;(x_i, y_i)&amp;lt;/tex&amp;gt; по убыванию &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt;  и положим их в очередь. Сперва достанем из очереди первые &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; элемента и сольём их в дерево и положим в конец очереди, затем сделаем то же самое со следующими двумя и т.д. Таким образом, мы сольём сначала &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; деревьев размера &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt;\dfrac{n}{2}&amp;lt;/tex&amp;gt; деревьев размера &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; и так далее. При этом на уменьшение размера очереди в два раза мы будем тратить суммарно &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; время на слияния, а всего таких уменьшений будет &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt;. Значит полное время работы алгоритма будет &amp;lt;tex&amp;gt;O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; ===&lt;br /&gt;
Будем строить дерево слева направо, то есть начиная с &amp;lt;tex&amp;gt;(x_1, y_1)&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;(x_n, y_n)&amp;lt;/tex&amp;gt;, при этом помнить последний добавленный элемент &amp;lt;tex&amp;gt;(x_k, y_k)&amp;lt;/tex&amp;gt;. Он будет самым правым, так как у него будет максимальный ключ, а по ключам декартово дерево представляет собой [[Дерево поиска, наивная реализация|двоичное дерево поиска]]. При добавлении &amp;lt;tex&amp;gt;(x_{k+1}, y_{k+1})&amp;lt;/tex&amp;gt;, пытаемся сделать его правым сыном &amp;lt;tex&amp;gt;(x_k, y_k)&amp;lt;/tex&amp;gt;, это следует сделать если &amp;lt;tex&amp;gt;y_k &amp;gt; y_{k+1}&amp;lt;/tex&amp;gt;, иначе делаем шаг к предку последнего элемента и смотрим его значение &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;. Поднимаемся до тех пор, пока приоритет в рассматриваемом элементе меньше приоритета в добавляемом, после чего делаем &amp;lt;tex&amp;gt;(x_{k+1}, y_{k+1})&amp;lt;/tex&amp;gt; его правым сыном, а предыдущего правого сына делаем левым сыном &amp;lt;tex&amp;gt;(x_{k+1}, y_{k+1})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Заметим, что каждую вершину мы посетим максимум дважды: при непосредственном добавлении и, поднимаясь вверх (ведь после этого вершина будет лежать в чьём-то левом поддереве, а мы поднимаемся только по правому). Из этого следует, что построение происходит за &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Случайные приоритеты ==&lt;br /&gt;
Мы уже выяснили, что сложность операций с декартовым деревом линейно зависит от его высоты. В действительности высота декартова дерева может быть линейной относительно его размеров. Например, высота декартова дерева, построенного по набору ключей &amp;lt;tex&amp;gt;(1, 1), \ldots, (n, n)&amp;lt;/tex&amp;gt;, будет равна &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Во избежание таких случаев, полезным оказывается выбирать приоритеты в ключах случайно.&lt;br /&gt;
&lt;br /&gt;
== Высота в декартовом дереве с случайными приоритетами ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement = В декартовом дереве из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; узлов, приоритеты &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; которого являются [[Дискретная случайная величина|случайными величинами]] c равномерным распределением, средняя глубина вершины &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=&lt;br /&gt;
&lt;br /&gt;
Будем считать, что все выбранные приоритеты &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; попарно различны.&lt;br /&gt;
&lt;br /&gt;
Для начала введём несколько обозначений:&lt;br /&gt;
* &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; {{---}} вершина с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;-ым по величине ключом;&lt;br /&gt;
* индикаторная величина &amp;lt;tex&amp;gt;A_{i, j} = \left\{\begin{array}{lllc} 1 ,&amp;amp;&amp;amp; x_i\  \text{is ancestor of} \ x_j\\ &lt;br /&gt;
0 ,&amp;amp;&amp;amp; \text{otherwise}\\&lt;br /&gt;
\end{array}\right.&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;d(v)&amp;lt;/tex&amp;gt; {{---}} глубина вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
В силу обозначений глубину вершины можно записать как количество предков:&lt;br /&gt;
:&amp;lt;tex&amp;gt;d(x_k) = \sum\limits_{i = 1}^{n} A_{i,k} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь можно выразить [[Математическое ожидание случайной величины|математическое ожидание]] глубины конкретной вершины:&lt;br /&gt;
:&amp;lt;tex&amp;gt;E(d(x_k)) = \sum\limits_{i = 1}^{n} Pr[A_{i,k} = 1] &amp;lt;/tex&amp;gt; {{---}} здесь мы использовали линейность математического ожидания, и то что &amp;lt;tex&amp;gt;E(X) = Pr[X = 1]&amp;lt;/tex&amp;gt; для индикаторной величины &amp;lt;tex&amp;gt;X&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;Pr[A]&amp;lt;/tex&amp;gt; {{---}} вероятность события &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;).&lt;br /&gt;
Для подсчёта средней глубины вершин нам нужно сосчитать вероятность того,  что вершина &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; является предком вершины &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt;, то есть &amp;lt;tex&amp;gt;Pr[A_{i,k} = 1]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Введём новое обозначение:&lt;br /&gt;
* &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt; {{---}}  множество ключей &amp;lt;tex&amp;gt;\{x_i, \ldots, x_k\}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\{x_k, \ldots, x_i\}&amp;lt;/tex&amp;gt;,  в зависимости от &amp;lt;tex&amp;gt;i &amp;lt; k&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;i &amp;gt; k&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;X_{k, i}&amp;lt;/tex&amp;gt; обозначают одно и тоже, их мощность равна &amp;lt;tex&amp;gt;|k - i| + 1&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=Для любых &amp;lt;tex&amp;gt;i \ne k&amp;lt;/tex&amp;gt; , &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; является предком &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; тогда и только тогда, когда &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; имеет наибольший приоритет среди &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=Если &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; является корнем, то оно является предком &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; и по определению имеет максимальный приоритет среди всех вершин, следовательно, и среди &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С другой стороны,  если &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; {{---}}  корень,  то &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; {{---}}  не предок &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; имеет максимальный приоритет в декартовом дереве; следовательно, &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; не имеет наибольший приоритет среди &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь предположим, что какая-то другая   вершина &amp;lt;tex&amp;gt;x_m&amp;lt;/tex&amp;gt; {{---}} корень. Тогда, если &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; лежат в разных поддеревьях, то &amp;lt;tex&amp;gt;i &amp;lt; m &amp;lt; k&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;i &amp;gt; m &amp;gt; k&amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;x_m&amp;lt;/tex&amp;gt; содержится в &amp;lt;tex&amp;gt;X_{i , k}&amp;lt;/tex&amp;gt;. В этом случае &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; {{---}} не предок &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt;, и наибольший приоритет среди &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt; имеет вершина с номером &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Наконец,  если &amp;lt;tex&amp;gt;x_i&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;x_k&amp;lt;/tex&amp;gt; лежат в одном поддереве,  то доказательство применяется по индукции: пустое декартово дерево есть тривиальная база,  а рассматриваемое поддерево является меньшим декартовым деревом. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Так как распределение приоритетов равномерное, каждая вершина среди &amp;lt;tex&amp;gt;X_{i, k}&amp;lt;/tex&amp;gt; может иметь максимальный приоритет,  мы немедленно приходим к следующему равенству: &lt;br /&gt;
: &amp;lt;tex&amp;gt;Pr[A_{i, k} = 1] = \left\{\begin{array}{lllc} \dfrac{1}{k - i + 1} ,&amp;amp;&amp;amp; k \ &amp;gt; \ i\\ &lt;br /&gt;
0 ,&amp;amp;&amp;amp; k\ =\ i\\&lt;br /&gt;
\dfrac{1}{i - k + 1} ,&amp;amp;&amp;amp; k \ &amp;lt; \ i\\&lt;br /&gt;
\end{array}\right.&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подставив последнее в нашу формулу с математическим ожиданием получим: &lt;br /&gt;
:&amp;lt;tex&amp;gt;E(d(x_k)) = \sum\limits_{i = 1}^{n} Pr[A_{i,k} = 1] = \sum\limits_{i = 1}^{k - 1}\dfrac{1}{k - i + 1} + \sum\limits_{i = k + 1}^{n}\dfrac{1}{i - k + 1} \leqslant &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\leqslant \ln(k) +  \ln(n - k)+2&amp;lt;/tex&amp;gt; (здесь мы использовали неравенство &amp;lt;tex&amp;gt;\sum\limits_{i = 1}^{n}  \dfrac{1}{i} \leqslant \ln(n) + 1&amp;lt;/tex&amp;gt;)&lt;br /&gt;
: &amp;lt;tex&amp;gt;\log(n)&amp;lt;/tex&amp;gt; отличается от &amp;lt;tex&amp;gt;\ln(n)&amp;lt;/tex&amp;gt; в константу раз, поэтому &amp;lt;tex&amp;gt;\log(n) = O(\ln(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В итоге мы получили что &amp;lt;tex&amp;gt;E(d(x_k)) = O(\log(n))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Таким образом, среднее время работы операций &amp;lt;tex&amp;gt;\mathrm{split}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm{merge}&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;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/Декартово_дерево Декартово дерево — Википедия]&lt;br /&gt;
*[http://rain.ifmo.ru/cat/data/theory/trees/treaps-2006/article.pdf Treaps и T-Treaps]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория:Деревья поиска]]&lt;/div&gt;</summary>
		<author><name>94.25.177.20</name></author>	</entry>

	</feed>