Informatyczny kącik olimpijski
Theater Tickets
Tym razem omówimy zadanie "Theater Tickets", które pojawiło się w konkursie Zinc 2018 organizowanym przez firmę Codility.
Zadanie. Dany jest -elementowy ciąg liczb naturalnych z przedziału od 1 do Oblicz, ile różnych trzyelementowych podciągów występuje w ciągu Dwa podciągi uznajemy za różne, jeśli różnią się na przynajmniej jednej pozycji. Przykładowo ma trzy różne podciągi: (występujący dwa razy), (występujący raz) oraz (występujący raz).
Niech oznacza podsłowo
Rozwiązanie
Pierwsze rozwiązanie będzie polegało na prostym zliczeniu podciągów trzyelementowych. Zauważmy, że wszystkich trzyelementowych ciągów o wartościach z przedziału jest gdyż każdy z trzech elementów można wybrać na sposobów. Niech jeśli jest podciągiem oraz w przeciwnym przypadku. Aby uzupełnić tablicę zliczającą wystarczy dla każdej trójki indeksów zaktualizować Ta faza zajmuje czas Wynikiem jest liczba komórek tablicy zliczającej o wartości 1. Rozwiązanie działa w czasie i pamięci
Rozwiązanie
Policzmy dla każdego prefiksu, ile zawiera on różnych dwuelementowych podciągów. Niech oznacza tę wartość dla -elementowego prefiksu Wyniki będziemy obliczali od najkrótszych do najdłuższych prefiksów. Oczywiście Zastanówmy się zatem, jak wyznaczyć dla Otóż gdzie oznacza liczbę takich dwuelementowych podciągów, które nie występują w ale występują w czyli takich, których drugim elementem jest Rozważmy więc takie dwuelementowe podciągi że i zliczmy te, które nie występują w Aby sprawdzić, które dwuelementowe podciągi wystąpiły wcześniej, można, podobnie jak w poprzednim rozwiązaniu, skorzystać z tablicy zliczającej. Wynik dla każdego prefiksu liczymy w czasie prefiksów jest zatem obliczamy w czasie
Przejdźmy teraz do wyznaczenia liczby różnych trzyelementowych podciągów Na początku dla każdej wartości od 1 do zapamiętajmy numer ostatniej pozycji, na której ta wartość występuje w Niech oznacza takie największe że Podciągi będziemy zliczali grupami, biorąc pod uwagę wartość ostatniego elementu. Otóż policzymy, ile jest podciągów, których ostatni element to odpowiednio a na koniec zsumujemy te wyniki. Zastanówmy się, jak dla ustalonego wyznaczyć liczbę różnych podciągów w postaci dla Jeśli nie występuje w to nie ma takich podciągów. W przeciwnym przypadku weźmy ostatnie wystąpienie w które znajduje się na pozycji Trzeci element mamy ustalony, zaś dwa pierwsze elementy możemy wybrać na sposobów, co jest równe liczbie różnych trzyelementowych podciągów kończących się liczbą Całkowita liczba trzyelementowych podciągów to co możemy obliczyć w znając Natomiast całe rozwiązanie działa w czasie i pamięci
Rozwiązanie
Spróbujmy przyspieszyć pierwszą fazę poprzedniego rozwiązania (obliczanie ). Na początku dla każdego prefiksu policzmy, ile zawiera on różnych wartości (podciągów jednoelementowych). Niech oznacza tę wartość dla -elementowego prefiksu, czyli Wyniki będziemy wyznaczali w kolejności rosnącej długości prefiksów. Oczywiście (mamy tylko jeden element). Zastanówmy się teraz, jak wyznaczyć dla Jeśli występowało wcześniej, wtedy W przeciwnym przypadku Do sprawdzania, czy występowało wcześniej, możemy wykorzystać tablicę zliczającą.
Przejdźmy teraz do obliczenia Podobnie jak wcześniej, wartości tej tablicy będziemy obliczali od najkrótszych do najdłuższych prefiksów. Dodatkowo niech dla oznacza numer ostatniej pozycji spośród przejrzanych elementów, na której wystąpił
Najpierw dla jednoelementowego prefiksu ustawiamy (nie ma podciągów dwuelementowych) oraz zapisujemy informację (ostatnie wystąpienie wartości na pozycji numer 1). Następnie przeglądamy kolejne prefiksy. Załóżmy, że obliczamy dla Otóż to powiększone o liczbę takich dwuelementowych podciągów które nie występują w Szukane podciągi są postaci - drugi element ma wartość Wszystkich takich podciągów w jest gdyż na tyle sposobów można wybrać Powinniśmy jednak odjąć te podciągi, które występują również w Jeśli występuje pierwszy raz, wtedy nie musimy nic odejmować. Jeśli natomiast występowało wcześniej, to weźmy jego poprzednie wystąpienie na pozycji Zauważmy, że jest ono drugim elementem podciągów (na tyle sposobów można wybrać element stojący przed poprzednim wystąpieniem ). Zatem otrzymaliśmy, że: Po obliczeniu możemy zaktualizować Wyznaczyliśmy w czasie Druga faza algorytmu jest analogiczna do tej opisanej w sekcji Rozwiązanie i działa w czasie co daje nam pełne rozwiązanie o złożoności czasowej