BOI 2016
CEOI 2017
BOI 2018
BOI 2019
BOI 2020
CEOI 2020
Wiosenne porządki
Dla dowolnego drzewa
definiujemy koszt wyczyszczenia tego drzewa jako
najmniejszą sumę odległości między odpowiednio sparowanymi liśćmi,
gdzie każdy liść ma należeć do dokładniej jednej pary
(więc da się wyczyścić drzewo wtedy i tylko wtedy, gdy liczba liści jest parzysta)
oraz każda krawędź drzewa ma należeć na co najmniej jednej najkrótszej ścieżce
między jakimiś sparowanymi liśćmi.
Mając dane drzewo -wierzchołkowe
oraz operacji ,
należy po każdej operacji wypisać minimalny koszt wyczyszczenia drzewa.
Każda operacja jest wykonywana niezależnie
(czyli na niezmienionym drzewie)
i polega na dodaniu dodatkowych synów do wybranych wierzchołków oryginalnego drzewa
(suma ilości dodanych synów po wszystkich operacjach nie przekracza ).
Podzadanie 2
Ograniczenia: zachodzi , istnieje krawędź między wierzchołkiem oraz dla
oraz nie są dodawane wierzchołki do wierzchołka .
Po dodaniu nowych liści, jeżeli istnieje wierzchołek posiadający co najmniej dwa liście,
to można liście zachłannie między sobą parować
(przy czym trzeba uważać na to, aby nie sparować ze sobą wszystkich liści,
które są synami wierzchołka niebędącego korzeniem).
Po tym można zauważyć, że nieważne jak sparujemy wierzchołki,
to ścieżka między każdą parą wierzchołków przechodzi przez korzeń,
więc wystarczy tylko rozpatrywać sumę odległości liści do korzenia.
Parzyste i nieparzyste wierzchołki
Można udowodnić, że w rozwiązaniu optymalnym,
każda krawędź zostanie wyczyszczona co najwyżej dwukrotnie
(szkic dowodu jest następujący -- jeżeli istnieje taka krawędź, która jest wyczyszczona
co najmniej trzykrotnie, to zamiast łączyć ze sobą pewną ilość par wierzchołków
po różnych stronach krawędzi, lepiej jest złączyć takie, co są po tej samej stronie).
Należy więc zminimalizować liczbę krawędzi drzewa, które zostaną wyczyszczone dwukrotnie.
Dla wygody ukorzeńmy sobie drzewo w wierzchołku niebędącym liściem.
Niech będzie ojcem wierzchołka .
Niech będzie nazwany parzystym, jeżeli w jego poddrzewie jest parzyście wiele liści
(analogicznie nieparzysty).
Dana krawędź od do na pewno będzie musiała być dwukrotnie czyszczona,
gdy jest parzystym wierzchołkiem.
Można też wykazać, że jeżeli jest nieparzysty, to zawsze można ją jednokrotnie czyścić.
Z tego wynika, że odpowiedzią dla dowolnego drzewa jest ,
gdzie to zbiór parzystych wierzchołków
i można to obliczyć w dla -wierzchołkowego drzewa poprzez pojedynczego DFS-a.
Jeżeli taki algorytm zostanie użyty dla każdego zapytania,
to otrzyma się rozwiązanie w złożoności ,
gdzie to liczba dodanych liści w -tym zapytaniu.
Podzadanie 4
Dla można użyć powyższego algorytmu.
Podzadanie 5 oraz 6
Gdy jest dodawany liść do wierzchołka , parzystość wierzchołków
się zmienia.
Podejściem używanym w obu podzadaniach jest utrzymywanie parzystości wierzchołków
oraz sumaryczną liczbę parzystych wierzchołków.
Zależnie od podzadania:
- w podzadaniu 5 podane drzewo jest pełnym binarnym drzewem,
więc dla każdego nowego liścia można w pętli zmienić wszystkie te wierzchołki,
gdyż głębokość drzewa wynosi .
Po operacji można analogicznie cofnąć dodanie tych liści.
- w podzadaniu 6 każda operacja dodaje dokładnie jeden liść,
więc można spreprocessować liczbę wierzchołków parzystych i nieparzystych
od korzenia do dla każdego wierzchołka ,
dzięki temu można obliczyć w jaki sposób zmieni się wartość w czasie stałym
dla jednej operacji.
Podzadanie 7 -- rozwiązanie z drzewem wirtualnym
Zauważmy, że gdy dodamy liść do wierzchołka oraz do wierzchołka ,
to wierzchołek nie zmieni parzystości
(ani wyższe wierzchołki na ścieżce do korzenia).
Niech zbiór to zbiór wierzchołków,
które w danej operacji mają dodanego co najmniej jednego nowego syna.
Niech będzie zbiorem wierzchołków
drzewa wirtualnego zdefiniowanego przez zbiór ,
czyli składa się ze zbioru
oraz każdej pary wierzchołków .
Można udowodnić, że
i można go skonstruować po prostu biorąc wszystkie wierzchołki
i biorąc kolejnych dwóch wierzchołków ciągu
posortowanego według numerów preorder całego drzewa.
Mając zbiór , można teraz skonstruować drzewo wirtualne ,
czyli takie drzewo o zbiorze wierzchołków ,
gdzie jest przodkiem w tym drzewie,
jeżeli jest przodkiem w oryginalnym drzewie.
W drzewie dla każdego wierzchołka policzmy liczbę
nowo dodanych liści w jego poddrzewie.
Jeżeli dla wierzchołka ta liczba jest nieparzysta,
to wszystkie wierzchołki w oryginalnym drzewie na ścieżce
od do (ale nie wliczając )
zmienią swoją parzystość.
Jeżeli ta liczba jest parzysta, nic się nie zmienia.
Zadanie więc zostało sprowadzone do obliczenia wyniku
po zmienieniu parzystości rozłącznych ścieżek w oryginalnym drzewie.
Korzystając z podejścia z podzadania 6,
w można policzyć zmianę w liczbie parzystych wierzchołków
po zmienieniu parzystości wierzchołków na wybranej ścieżce
(korzystając z podejścia, że ścieżka od do jego przodka
to jest ścieżka od do korzenia,
„odjąć” ścieżka od ojca do korzenia).
Podzadanie 7 -- rozwiązanie z HLD
Operacje z podzadania 6 można rozwiązać w
za pomocą heavy-light decomposition z operacjami zmienienia stanu wierzchołków
(parzysty lub nieparzysty)
na wybranej ścieżce oraz policzenia liczby wierzchołków z danym stanem.
Podzadanie 7 -- rozwiązanie z mniejszym do większego
Dla każdego wierzchołka spreprocessujmy indeksy operacji,
które sprawią, że w tym wierzchołku zostanie doczepiony nowy syn.
Wtedy, DFS-em od liści do korzenia można sparować niesparowane liście.
Takie niesparowane liście
(identyfikowane poprzez numer oryginalnego liścia lub numer operacji dodającej tego liścia)
można trzymać w secie,
a w każdym wierzchołku w tym DFS-ie należy w pewien sposób
złączyć takie dwa zbiory.
Jeżeli spotkamy dwóch synów mających niesparowany wierzchołek dodany przez taką samą operację,
to aktualny wierzchołek jest LCA tych dwóch liści,
więc można odpowiednio policzyć zmianę w liczbie parzystych wierzchołków.
Taki algorytm daje tylko zmianę wyniku w porównaniu do oryginalnego drzewa.
Należy więc jeszcze policzyć wynik oryginalnego drzewa, bez żadnych operacji.
Żeby zachować złożoność mniejszą niż kwadratowa, można
zawsze łączyć mniejszy zbiór do większego
(co jest potocznie nazywane „metodą mniejszy do większego”),
otrzymując złożoność .