Level ancestor1 - базовая задача, в которой у нас есть корневое дерево и для заданной вершины v и числа k мы хотим знать k - ого предка вершины v.

Медленное решение

Для понимания сложного решения иногда полезно разобраться с самым медленным, но зато самым простым способом решить, а потом его улучшать. В этом конкретном случае мы можем обойти дерево с помощью dfs-а, и запомнить для каждой вершины ее предка, если они у нас ещё не хранятся, после чего просто k раз переходить из вершины в предка, чтобы получить искомый ответ. В худшем случае, то есть бамбуке, все это работает за O(n) на запрос и O(n) на предподсчет.

Бинарные подъемы

Медленное решение, конечно, хорошее, но есть что улучшать. Давайте увеличим кол-во предподсчета, вспомнив, что любое число представимо в виде суммы степеней двоек. Давайте для каждой вершины посчитаем подъем на все степени 2 от 1 до . Сделать это можно легко с помощью динамического программирования, для мы записываем предка вершины, а для корня его же самого, что не разбираться с несуществующими вершинами, а для всех остальных уровней можно просто посчитать по формуле: Теперь для того чтобы подняться на k мы просто ищем наибольшую степень 2, которая меньше, либо равна k и поднимаемся на нее, и получаем сложность с предподсчетом за . Этот вариант лучше всего использовать на олимпиадах, ведь пишется быстро и легко, а следующие реализации, хоть и быстрее, но пишутся гораздо труднее и зачастую игра не стоит свеч.

Код
long long lev_anc(long long x, long long k) {
	long long cnt = 0;
	while (k) {
		if (k & 1) {
			x = bin_up[x][cnt];
		}
		k >>= 1;
		cnt++;
	}
	return x;
}

Ladder decomposition

Воспользуемся нашей замечательной декомпозицией. Теперь можно насчитать для каждой вершины бинарные подъемы из предыдущего пункта и весь этот предподсчет работает за . Отлично, поймем теперь как отвечать на запросы за . Из вершины x мы можем подняться на и попасть в вершину v. Утверждение. В пути , в котором лежит v, обязательно лежит и ответ. Доказательство. Так как v лежит в пути , то начало пути либо сам v, либо его предок. X потомок v, значит длина пути от v до конца хотя бы , а значит длина пути от начала до v тоже хотя бы . Тогда раз , то и искомая вершина лежит в . Получается, нам остается подняться на максимальную степень двух не превосходящую k1 и подсчитать ответ за .

Прокачанный ladder decomposition

Заметим, что в ladder decomposition у нас ровно L путей, где L - кол-во листьев, что логично, ведь все пути заканчиваются в листьях и нет ни одного листа, в котором заканчивается 2 пути. Тогда давайте решим задачу только для листьев, а все запросы для нелистьев будем сводить к запросам от листьев. Для этого нам надо также подсчитать для каждой вершины ее листа потомка, что можно также сделать в dfs, а также считать бинапы только от листьев. Итоговая сложность предподсчета падает до , а скорость ответа на запрос не меняется, ведь сводить запрос к листу можно за .

Macro-micro tree

Попробуем улучшить предыдущий алгоритм с помощью корнячки, а точнее одной из ее идей - деление объектов на легкие и тяжелые. Пусть S = . Тогда пройдемся по всему графу и мысленно удалим вершину v, если . Тогда у оставшегося дерева не более листьев, а значит, если мы на этой части дерева применим предыдущий алгоритм то получим сложность предподсчета, равную: У нас остались только поддеревья, мощность которых не превышает S. Утверждение. Количество таких деревьев не превышает . Доказательство. Сделаем эйлеров обход такого дерева, причем при каждом передвижении, если мы двигаемся вверх, то записываем в строку 1, иначе 0. После обхода мы получим бинарную строку длиной 2S - 2, а значит количество таких деревьев не превышает количества бинарных строк длины 2S, а их: Тогда давайте сделаем полный предподсчет для каждой вершинки во всех поддеревьях, мощность которых не превышает S, это будет работать за:

Примечание

Никогда не пишите этот алгоритм, он бессмысленен, ведь улучшается только предподсчет, для олимпиад это слишком сложно и долго писать и ограничения никогда не бывают такие жесткие, а в прод задачах о предподсчёте редко беспокоятся.

Footnotes

  1. Не имеет нормального перевода, так что будет локализирована мной, как проблема уровня предка 2