Informatyczny kącik olimpijski
Gotówka, Startup
Tym razem omówimy dwa zadania, które na pierwszy rzut oka wyglądają podobnie, jednak w istocie są różne. Pierwsze z nich pochodzi z II etapu IX Olimpiady Informatycznej Gimnazjalistów, zaś drugie z Bałkańskiej Olimpiady Informatycznej Juniorów w 2015 roku.
Zadanie (Gotówka). Danych jest transakcji opisanych za pomocą ciągu liczb całkowitych (dodatnie liczby to wpływy, zaś ujemne to wydatki). Poprawnym ciągiem transakcji nazywamy taki, podczas którego stan konta nigdy nie spadnie poniżej zera. Ile jest permutacji ciągu które są poprawnymi ciągami transakcji?
Rozwiązanie .
Pierwszy, najbardziej intuicyjny, pomysł polega na wygenerowaniu wszystkich permutacji ciągu oraz zliczeniu tych, które są poprawne. Sprawdzenie, czy dana permutacja transakcji jest poprawna, możemy wykonać w czasie liniowym od jej długości. Wystarczy, że sprawdzimy, czy suma każdego prefiksu jest nieujemna. Niestety, takie podejście jest czasochłonne i działa w czasie
Rozwiązanie .
W tym rozwiązaniu wykorzystamy technikę programowania dynamicznego. Niech oznacza liczbę poprawnych ciągów transakcji, które są permutacją ciągu Obliczmy wartość dla każdego podciągu ciągu Jeśli jest pusty lub suma elementów podciągu jest ujemna, wtedy W przeciwnym przypadku istnieje przynajmniej jedna poprawna permutacja ciągu Aby obliczyć rozważmy możliwości wybrania transakcji, która zostanie wykonana jako ostatnia. Liczba poprawnych ciągów transakcji, przy założeniu, że ostatnia transakcja to wynosi (liczba poprawnych uporządkowań pozostałych transakcji). Zatem:
Liczba poprawnych permutacji dla całego ciągu to
Ciąg ma podciągów. Obliczenie dla -elementowego podciągu kosztuje operacji, zaś -elementowych podciągów jest Zatem obliczenie wszystkich wartości wymaga wykonania
operacji. Rozwiązanie działa w czasie
Zadanie (Startup). Dany jest ciąg transakcji opisanych za pomocą ciągu liczb całkowitych (dodatnie liczby to wpływy, zaś ujemne to wydatki). Poprawnym ciągiem transakcji nazywamy taki, podczas którego stan konta nigdy nie spadnie poniżej zera. Ile jest rotacji ciągu które są poprawnymi ciągami transakcji? Rotacją ciągu nazywamy -elementowy ciąg, powstały poprzez konkatenację sufiksu i prefiksu ciągu Rotacjami ciągu są: i
Rozwiązanie .
Zauważmy, że wszystkich rotacji jest (każdy element wyznacza początek rotacji). Wystarczy zatem każdą z nich rozpatrzyć niezależnie. Sprawdzenie, czy dana rotacja jest poprawnym ciągiem transakcji, możemy wykonać w czasie liniowym od jej długości. Wystarczy sprawdzić, czy suma każdego prefiksu jest nieujemna. W ten sposób otrzymujemy rozwiązanie, które działa w czasie
Rozwiązanie . Zastanówmy się teraz, czy możemy przyspieszyć fazę sprawdzania, czy dana rotacja jest poprawnym ciągiem transakcji - oczywiście możemy. Zacznijmy od sklejenia dwóch kopii ciągu w jeden ciąg :
Wówczas każda rotacja jest podsłowem ciągu
Niech będzie ciągiem sum prefiksowych dla ciągu (tzn. ).
Załóżmy, że chcemy sprawdzić poprawność rotacji Odpowiadającym podsłowem słowa jest Podsłowo jest poprawnym ciągiem transakcji, jeśli każdy prefiks ma nieujemną sumę:
Powyższy warunek możemy równoważnie zapisać jako
oraz jako
Zauważmy, że powyższy warunek jest prawdziwy wtedy i tylko wtedy, gdy
W celu wyznaczenia minimum na przedziale możemy skorzystać ze struktury drzewa przedziałowego rozpiętego na ciągu Drzewo przedziałowe pozwala w czasie znajdować minimum na przedziale - czyli sprawdzać, czy dana rotacja jest poprawna. Wszystkich rotacji jest zatem rozwiązanie działa w czasie