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