Piotr Sankowski - p. 1/27
przypomnienie czas O(log 2 n), jak to zrobić w czasie O(log n), jak to zrobić w pesymistycznym czasie O(log n) (szkic). - p. 2/27
Operacje na dynamicznych drzewach: parent(v) ojciec v, root(v) korzeń drzewa do którego należy v, cost(v) waga krawędzi (v, parent(v)), mincost(v) wierzchołek w taki, że (w, parent(w)) ma najmniejsza wagę na ścieżce z v do korzenia, update(v, x) dodaj x do wag krawędzi na ścieżce z v do korzenia, link(v, w, x) dodaj krawędź (v, w) o wadze x łacz ac drzewa (v musi być korzeniem), cut(v) usuń krawędź (v, parent(v)), evert(v) uczyń v korzeniem drzewa. - p. 3/27
Drzewo dzielimy na ścieżki krawędzie kreskowane i sztywne. Ogony ścieżek sa na górze, głowy na dole. Każda ścieżkę trzymamy w strukturze umożliwiajacej na wykonywanie operacji w czasie O(log n). dpartent(v) i dcost(v) dla ogona v opisuja krawędź kreskowana. - p. 4/27
Dynamiczne ścieżki path(v) ścieżka (identyfikator) do której należy v, head(p) głowa ścieżki p, tail(p) ogon ścieżki p, be f ore(v) poprzedni wierzchołek przed v na path(v), a f ter(v) następny wierzchołek po v na path(v), pcost(v) waga krawędzi (v, a f ter(v)), pmincost(p) wierzchołek v taki, że (v, a f ter(v)), pupdate(p, x) dodaje x do wagi krawędzi na p, reverse(p) odwraca kierunek p, concatenete(p, q, x) łaczy p i q poprzez dodanie krawędzi (tail(p), head(q)) o wadze x i zwraca wynikowa ścieżkę, split(v) dzieli path(v) na trzy części poprzez usunięcie krawędzi sasiaduj acych z v. Zwraca listę [p, q, x, y], gdzie p i q to nowe ścieżki, a x i y to wagi usuniętych krawędzi. - p. 5/27
splice(p) zamienia krawędź (tail(p), dparent(tail(p))) na sztywna. - p. 6/27
expose(p) zamienia wszystkie krawędzie na ścieżce od v do korzenia drzewa na sztywne, oraz kasuje sztywna krawędź idac a w dół z v. - p. 7/27
Przed wykonaniem operacji na drzewie odwołujacej się do danego wierzchołka v wykonujemy najpierw na nim operację expose(v). Twierdzenie 1 W ciągu m operacji na dynamicznych drzewach wykonanych jest O(m log n) operacji na ścieżkach. Wniosek 1 Operacje na dynamicznych drzewach można wykonać w amortyzowanym czasie O(log 2 n). - p. 8/27
Obciażone drzewa wyszukiwań Dla każdego liścia v zadajemy dodatni a wagę wt(v). Dla każdego węzła definiujemy rangę rank(v) tak by spełniała: (i) jeżeli v jest liściem to rank(v) = log wt(v), (ii) jeżeli v jest węzłem to rank(v) 1 + log wt(v), gdzie waga węzła to suma wag dzieci, (iii) jeżeli w ma ojca v, to rank(w) rank(v) i nierówność jest ostra gdy w jest liściem, (iv) jeżeli w ma dziadka v, to rank(w) < rank(v). (tab) - p. 9/27
Obciażone drzewa wyszukiwań Lemat 1 Jeżeli v jest liściem w obciążonym drzewie wyszukiwań o korzeniu u, głębokość v wynosi co najwyżej 2(rank(u) rank(v)) 2 log( wt(u) wt(v) ) + 4. Z własności (iv) wynika, że głębokość v wynosi co najwyżej 2(rank(u) rank(v)). Z własności (i) i (ii) otrzymujemy rank(u) rank(v) log( wt(u) wt(v) ) + 2. Łacz ac te dwie nierówności otrzymujemy tezę lematu. - p. 10/27
Obciażone drzewa wyszukiwań Lemat 2 Połączenie dwóch drzew o korzeniach p i q można wykonać w amortyzowanym czasie O( rank(p) rank(q) ). Korzeń powstałego drzewa ma rangę max {rank(p), rank(q)} bądź max {rank(p), rank(q)} + 1. (tab) - p. 11/27
Obciażone drzewa wyszukiwań Lemat 3 Operacja split(v) zajmuje czas amortyzowany O(rank(p) rank(v)), gdzie p to oryginalny korzeń drzewa. Niech q i r to lewe i prawe zwrócone drzewo. Jeżeli q = null to rank(q) rank(p) + 1; jeżeli r = null to rank(r) rank(p) + 1. Jako efekt uboczny otrzymujemy rank(p) rank(q) + 1 kredytów jeżeli q = null oraz rank(p) rank(r) + 1 kredytów jeżeli r = null. (tab) - p. 12/27
Niech size(v) oznacza liczbę potomków v w drzewie. Wagę liścia definiujemy jako wt(v) = size(v) jeżeli sztywna krawędź nie wychodzi z v, wt(v) = size(v) size(w) jeżeli sztywna krawędź (v, w) wychodzi z v. Wagi s a określone lokalnie więc można je przeliczać w czasie wykonywania operacji. - p. 13/27
Lemat 4 Każdy węzeł w obciążonym drzewie wyszukiwań reprezentujący sztywną ścieżkę ma wagę 1 wt(v) n, gdzie n to całkowita liczba wierzchołków. Czyli 0 rank(v) 1 + log n. Niech p będzie korzeniem drzewa zawierajacego v. Z definicji wagi wynika 1 wt(v) wt(p) = size(p) n. - p. 14/27
Twierdzenie 2 Jeżeli użyjemy drzew obciążonych do reprezentacji sztywnych ścieżek, to ciąg m operacji dynamicznych wykona się w czasie O(m log n). Nie właczaj ac operacji splice, operacje wykonuja się w czasie O(m log n), co wynika z Lematu 4. Tydzień temu pokazaliśmy, że wyjatkowych operacji splice jest O(m). Pozostaje nam pokazać, że O(m log n) normalnych operacji splice zajmuje czas O(m log n). - p. 15/27
Rozważmy i-ta normalna operacje splice wykonywana w trakcie operacji expose. Niech u będzie ogonem ścieżki powiększanej, p będzie ścieżka zawierajac a u przed i-tym splice-em, v będzie ojcem u, s ścieżka zawierajac a v przed pierwszym splice-em, oraz s niech będzie ścieżka zawierajac a v (i u) po i-tym splice-ie. - p. 16/27
Będziemy używać także p, p, s, s do oznaczenia korzeni drzew reprezentujacych te ścieżki. - p. 17/27
Niech wt(v) będzie waga v przed tym splice-em, a wt (v) waga v po splice-ie. Podobnie ustalmy rank(v) oraz rank (v). Wtedy rank(s) rank(v) + 1, z (iii), bo s = v więc v jest liściem, rank(s) 1 + log wt(v) 1 + log wt(p) rank(p). Podobnie pokazujemy, że rank(s) rank(p ). - p. 18/27
Operacje wykonywane w splice(p) v = dparent(tail(p)), [q, r, x, y] = split(v), jeżeli q = null to dparent(tail(q)) = v, dcost(tail(q)) = x, p = concatenate(p, path(v), dcost(tail(p))), jeżeli r = null to concatenate(p, r, y). - p. 19/27
Amortyzowany czas na na wykonanie split(v) w splice-ie zajmuje O(rank(s) rank(v)) = O(rank(s) rank(p)). Ponieważ jest to normalny splice to zostaje nam nadmiar rank(s) rank(q) + 1 0 kredytów, gdzie q jest lewym drzewem otrzymanym ze split(v). Mamy teraz rank (s ) rank (v) + 1 1 + log wt (v) 1 + log wt(q) rank(q). Z Lematu 2 mamy rank(s ) rank(p ). - p. 20/27
Liczba kredytów potrzebnych na wykonanie concatenate(p, path(v),...) wynosi rank(p ) rank (v) + 1 2rank(s ) rank(p ) rank (v) + 1 rank(s ) rank(p ) + rank(s ) rank(q) + 2, ponieważ z właściwości (ii) mamy rank (v rank(q) 1. Ponieważ mamy rank(s) rank(q) + 1 w ręku, potrzebujemy jeszcze rank(s ) rank(p ) + rank(s ) rank(s) + 1 2(rank(s ) rank(p )) + 1 nowych kredytów. - p. 21/27
Ostatnia operacja to concatenate(p, r, y). Podobnie jak dla pierwszego concatenate dostajemy, że wymaga on 2(rank(s ) rank(p )) + 1 kredytów. Łacz ac te oszacowania otrzymujemy ograniczenie O(rank(s) rank(p) + rank(s ) rank(p )) na amortyzowany czas wykonania splice-a. Zauważmy, że rank(s) rank(p) oraz rank(s ) rank(p ). - p. 22/27
Jeżeli wyszumujemy to oszacowanie po wszystkich normalnych splice-ach wykonywanych w trakcie expose suma ta składa się teleskopowo. ostatecznie dostajemy ograniczenie O(k + log n) na czas wykonania jednego expose-a, gdzie k to liczba splice-ów. Korzystajac z tego, że splice-ów jest co najwyżej O(m log n) otrzymujemy ograniczenia czasowe O(m log n) na wykonanie m operacji. - p. 23/27
Pokazaliśmy algorytm amortyzowany działajacy w czasie O(log n) dla operacji na dynamicznych drzewach. Czy można wykonać te operacje w czasie pesymistycznych O(log n)? TAK - p. 24/27
Krawędź (v, w) jest ciężka jeżeli 2size(v) > size(w). Krawędź nazwiemy sztywna wttw gdy jest ona ciężka. Teraz dowolna ścieżka od v do korzenia zawiera co najwyżej log n + 1 kreskowanych krawędzi, czyli przechodzi przez co najwyżej log n + 1 sztywnych ścieżek. - p. 25/27
Operacje wykonujemy tak jak poprzednio. Problem jest taki, że expose mogło zamienić lekkie krawędzie na sztywne i ciężkie na kreskowane. Wprowadzamy operację naprawiajac a conceal(p), która zamienia na kreskowane wszystkie lekkie krawędzie na p i zamienia na sztywne wszystkie ciężkie krawędzie sasiednie z p. - p. 26/27
musimy mieć metodę szukania lekkich i ciężkich krawędzi rozbudowanie struktur przechowujacych ścieżki; - p. 27/27
musimy mieć metodę szukania lekkich i ciężkich krawędzi rozbudowanie struktur przechowujacych ścieżki; używamy globalnie obciażonych drzew wyszukiwania lepsze pesymistyczne czasy wykonania; - p. 27/27
musimy mieć metodę szukania lekkich i ciężkich krawędzi rozbudowanie struktur przechowujacych ścieżki; używamy globalnie obciażonych drzew wyszukiwania lepsze pesymistyczne czasy wykonania; musimy dla każdego wierzchołka trzymać jakie wchodza do niego krawędzie kreskowane używamy globalnie obciażonych drzew wyszukiwania; - p. 27/27
musimy mieć metodę szukania lekkich i ciężkich krawędzi rozbudowanie struktur przechowujacych ścieżki; używamy globalnie obciażonych drzew wyszukiwania lepsze pesymistyczne czasy wykonania; musimy dla każdego wierzchołka trzymać jakie wchodza do niego krawędzie kreskowane używamy globalnie obciażonych drzew wyszukiwania; przeprowadzamy jeszcze bardziej skomplikowana analizę... i wszystko wychodzi; - p. 27/27