Centroid decomposition — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (Введение)
м (Введение)
Строка 5: Строка 5:
 
Задача 1
 
Задача 1
 
{{Задача
 
{{Задача
|definition = Есть массив <tex>a[]</tex> положительных целых чисел из <tex>n</tex> элементов и числа <tex>W >= 0</tex> и <tex>l</tex> . Требуется найти количество пар <tex>(i, j)</tex> индексов массива, таких что <tex>|j - i| \leqslant l </tex> и <tex>\sum_{i=0}^{n - 1} [a[i]] \leqslant W</tex>.
+
|definition = Есть массив <tex>a[]</tex> положительных целых чисел из <tex>n</tex> элементов и числа <tex>W \geqslant 0</tex> и <tex>l</tex> . Требуется найти количество пар <tex>(i, j)</tex> индексов массива, таких что <tex>|j - i| \leqslant l </tex> и <tex>\sum_{i=0}^{n - 1} [a[i]] \leqslant W</tex>.
 
}}
 
}}
 
Задача 2:
 
Задача 2:
Строка 15: Строка 15:
 
}}
 
}}
 
Для начала решим обе задачи.  
 
Для начала решим обе задачи.  
Первая задача решается методом [[Сортировка_слиянием|qevide&conqure (рус. разделяй и властвуй)]] - давайте разделим массив <tex>a[0...n-1]</tex> на 2 массива <tex>a[0...\frac{n}{2} - 1]</tex> и <tex>a[\frac{n}{2}...n-1]</tex> и рекурсивно решим задачу для каждого из них. Осталось научиться находить количество искомых пар <tex>(i, j)</tex>, таких что <tex>i < \frac{n}{2}, j >= \frac{n}{2}</tex>. Для этого воспользуемся другой известной техникой - методом двух указателей. Посчитаем массив префиксных сумм для правой половины <tex>pref[i] = \sum_{j=n/2}^{i} [a[j]]</tex> и суффиксных (<tex>suf[i] = \sum_{j=i}^{n/2 + 1} [a[i]]</tex>) - для левой. Заведем два указателя (<tex>p1</tex> и <tex>p2</tex>). Изначально установим <tex>p1 = \frac{n}{2} - l + 1, p2 = \frac{n}{2}</tex>. Пока <tex>p2 - 1> \frac{n}{2}</tex> и
+
Первая задача решается методом [[Сортировка_слиянием|qevide&conqure (рус. разделяй и властвуй)]] - давайте разделим массив <tex>a[0...n-1]</tex> на 2 массива <tex>a[0...\frac{n}{2} - 1]</tex> и <tex>a[\frac{n}{2}...n-1]</tex> и рекурсивно решим задачу для каждого из них. Осталось научиться находить количество искомых пар <tex>(i, j)</tex>, таких что <tex>i < \frac{n}{2}, j \geqslant \frac{n}{2}</tex>. Для этого воспользуемся другой известной техникой - методом двух указателей. Посчитаем массив префиксных сумм для правой половины <tex>pref[i] = \sum_{j=n/2}^{i} [a[j]]</tex> и суффиксных (<tex>suf[i] = \sum_{j=i}^{n/2 + 1} [a[i]]</tex>) - для левой. Заведем два указателя (<tex>p1</tex> и <tex>p2</tex>). Изначально установим <tex>p1 = \frac{n}{2} - l + 1, p2 = \frac{n}{2}</tex>. Пока <tex>p2 - 1> \frac{n}{2}</tex> и
  
 
<tex>pref[p2] + suf[p1] > W </tex> будем уменьшать <math>p2</math> на <math>1</math>. Если после этого <math>pref[p2] + suf[p1] \leqslant W</math>, то к ответу прибавим <math>(p2 - \frac{n}{2} + 1) * (\frac{n}{2} - p1)</math>, посго, увеличим <math>p1</math> на <math/math>. Так будем делать, пока <math>p1 < \frac{n}{2}</math>. В конце сложим текущий ответ и ответы для половин массива - получим ответ на задачу.
 
<tex>pref[p2] + suf[p1] > W </tex> будем уменьшать <math>p2</math> на <math>1</math>. Если после этого <math>pref[p2] + suf[p1] \leqslant W</math>, то к ответу прибавим <math>(p2 - \frac{n}{2} + 1) * (\frac{n}{2} - p1)</math>, посго, увеличим <math>p1</math> на <math/math>. Так будем делать, пока <math>p1 < \frac{n}{2}</math>. В конце сложим текущий ответ и ответы для половин массива - получим ответ на задачу.

Версия 00:40, 14 июня 2017

Centroid decomposition (рус. центроидная декомпозиция) - это структура данных, позволяющая отвечать на запросы на дереве. Чаще всего это запросы, связанные с нахождением функции на вершинах, связанных неравенством на расстояние между ними в дереве. Также иногда применяется для запросов на путях в дереве.

Введение

Рассмотрим 2 задачи на обычном массиве (в дальнейшем мы будем их обобщать на случай дерева): Задача 1

Задача:
Есть массив [math]a[][/math] положительных целых чисел из [math]n[/math] элементов и числа [math]W \geqslant 0[/math] и [math]l[/math] . Требуется найти количество пар [math](i, j)[/math] индексов массива, таких что [math]|j - i| \leqslant l [/math] и [math]\sum_{i=0}^{n - 1} [a[i]] \leqslant W[/math].

Задача 2:

Задача:
Есть прямая дорога, на которой расположены [math]n[/math] городов. В некоторых городах есть госпитали, которые могут принимать больных. Поступают запросы вида :

1) дан город [math]v[/math], в котором находится больной и требуется найти такой город [math]u[/math], что [math]abs{u - v}[/math] минимально возможное. 2) дан город [math]v[/math] и сказано, что больше он не будет принимать больных

3) дан город [math]v[/math] и сказано, что теперь он может принимать больных

Для начала решим обе задачи. Первая задача решается методом qevide&conqure (рус. разделяй и властвуй) - давайте разделим массив [math]a[0...n-1][/math] на 2 массива [math]a[0...\frac{n}{2} - 1][/math] и [math]a[\frac{n}{2}...n-1][/math] и рекурсивно решим задачу для каждого из них. Осталось научиться находить количество искомых пар [math](i, j)[/math], таких что [math]i \lt \frac{n}{2}, j \geqslant \frac{n}{2}[/math]. Для этого воспользуемся другой известной техникой - методом двух указателей. Посчитаем массив префиксных сумм для правой половины [math]pref[i] = \sum_{j=n/2}^{i} [a[j]][/math] и суффиксных ([math]suf[i] = \sum_{j=i}^{n/2 + 1} [a[i]][/math]) - для левой. Заведем два указателя ([math]p1[/math] и [math]p2[/math]). Изначально установим [math]p1 = \frac{n}{2} - l + 1, p2 = \frac{n}{2}[/math]. Пока [math]p2 - 1\gt \frac{n}{2}[/math] и

[math]pref[p2] + suf[p1] \gt W [/math] будем уменьшать [math]p2[/math] на [math]1[/math]. Если после этого [math]pref[p2] + suf[p1] \leqslant W[/math], то к ответу прибавим [math](p2 - \frac{n}{2} + 1) * (\frac{n}{2} - p1)[/math], посго, увеличим [math]p1[/math] на <math/math>. Так будем делать, пока [math]p1 \lt \frac{n}{2}[/math]. В конце сложим текущий ответ и ответы для половин массива - получим ответ на задачу.

Вторая задача имеет запросы на изменение и поэтому надо применить динамическую версию qevide&conqure - дерево отрезков. Построим дерево отрезков, поддерживающее 2 вида запросов : присвоение в точке и минимум на отрезке. Изначально сделаем так, чтобы дереву отрезков соответствовал массив [math]b[][/math], такой что [math]b[i] = 0[/math], если в i-м городе принимает госпиталь и [math]b[i] = 1[/math] иначе. Когда в каком-то городе открывается/закрывается госпиталь - делаем запрос на изменение в дереве отрезков. Когда требуется узнать ближайщий госпиталь к [math]i[/math]-му городу, можно воспользоваться одной из следующих идей : а) ([math]O(n \dot log^2(n)[/math]) Бинарным поиском ищем ближайший слева и ближайший справа к i-му городу госпиталь (такой город [math]j[/math], что [math]min(i...j) = 1[/math]). Для этого внутри бинарного поиска каждый раз делаем запрос на поиск минимума в дереве отрезков. б) ([math]O(n \dot log(n)[/math]) Будем одним спуском/подъемом по дереву определять, куда нам нужно идти (в левое или правое поддерево), тем самым делая одновоременно и бинарный поиск, и спуск/подъем по дереву.

Статическая центроидная декомпозиция

Перейдем к обобщению поставленных задач на случай дерево. Начнем, как и полагается, с первой:

Задача:
Есть взвешенное дерево [math]t[/math] из [math]n[/math] вершин, в каждой вершине которого написаны положительные целые числа. Также по-прежнему даны числа [math]W \gt = 0[/math] и [math]l[/math]. Требуется найти количество пар [math](i, j)[/math] вершин дерева, таких что расстояние между ними не превосходит [math]l[/math] по числу ребер и не превосходит [math]W[/math] по сумме весов.


Для решения новой задачи применим ту же идею, что и была до этого - разделяй и властвуй. Для этого нам потребуется следующий объект :


Определение:
Центроидом дерева (англ. centroid) называется такая вершина [math]v[/math] дерева [math]t[/math], после удаления которой дерево разбивается на несколько ([math]k[/math]) поддеревьев [math]t_1, t_2,..., t_k[/math], таких что для каждого [math]i[/math] : [math]|t_i| \leqslant \frac{n}{2}[/math], т.е. размер каждого поддерева не превосходит половины размера исходного дерева.


Но в случае дерева эта идея будет формулироваться так : разделим дерево на несколько поддеревьев [math]t_1, t_2,..., t_k[/math] одной из вершин ([math]v[/math]), таких что каждое из них имеет размер, не превосходящий [math] \frac{n}{2}[/math]. Такая вершина [math]v[/math] будет называться центроидом дерева (доказательство её существования и алгоритм нахождение см. далее). Предположим, что мы сумели найти центроид за [math]O(n)[/math], где [math]n[/math] - размер дерева. Тогда, как и в упрощенной версии задачи - рекурсивно найдем ответ для всех поддеревьев [math]t_1, t_2,..., t_k[/math], после чего попытаемся найти недостающие пары вершин, находящиехя в разных поддеревьях и удовлетворяющих вопросу задачи. 

Лемма о центроиде

Алгоритм нахождения центроида в произвольном дереве

Динамическая центроидная декомпозиция (дерево центроидной декомпозиции)

Варианты реализации

См. также

Примечания