Задача 1
Дано корневое дерево и число $$$k$$$. Для каждой вершины $$$u$$$ найти кол-во вершин в поддереве вершины $$$u$$$ отдаленных от $$$u$$$ на расстояние не более $$$k$$$ рёбер.
Задача 2
Дано дерево и число $$$k$$$. Для каждой вершины $$$u$$$ найти кол-во вершин во всем дереве отдаленных от $$$u$$$ на расстояние не более $$$k$$$ рёбер. (источник) (похожая задача)
В этом блоге рассмотрим решение Задачи 1 за $$$O(N)$$$. При этом используется забавная структура — RQ на stack-е с запросами $$$O(1)$$$ (по сути это будет префикс-сумма).
Вообще Задача 1 возникла при попытке (видимо не удачной) решить Задачу 2, для которой есть решения за $$$O(N \ln N)$$$, но я пока не знаком с этими темами и не хочу напутать:
через Centroid Decomposition
для похожей задачи через SplayTree и прочее (см. комментарии про задачу D) $$$ $$$
Решение
Решать Задачу 1 будем через DFS. При обходе будем хранить стек чисел, каждое значение которого будет соответствовать ответу для вершины определенного поддерева. Длинна стека $$$h$$$ будет соответствовать глубине рекурсии в DFS.
При входе в новую вершину, увеличиваем значения в интервале стека $$$[h-k, h)$$$ на единицу. И push-ем $$$1$$$ в стек.
При выходе из вершины, сохраняем последнее значения стека в вершину соответствующего поддерева. И затем делам pop в стеке.
Оказывается эти операции с стеком можно выполнять за $$$O(1)$$$:
Для увеличения на интервале выполняем:
diff[l] -= delta; diff[r] += delta;При pop() выполняем "пропихивание":
diff[l-1] += diff[l];
После поисков нашёл задачу где используется что-то схожее — хранение пути от корня в DFS: F. Два поддерева (решение).
Хотелось бы воспользоваться rerootin-ом и с помощью Задачи 1 решить Задачу 2. Однако тогда для корня надо знать результаты для дистанций { $$$k, k-1$$$ }, чтобы подсчитать результат для дистанции { $$$k$$$ } у ребёнка. В итоге у ребёнка теряется результат для дистанции { $$$k-1$$$ }, и как его можно оптимально восстанавливать не понятно.
Удивительно, но мне как-то мало попалось статьей об этих задачах, надеюсь этот блог будет полезен!







