Informatyczny kącik olimpijski
Trzej znajomi
W tym odcinku omówimy rozwiązanie zadania "Trzej znajomi", które pojawiło się na drugim etapie XIII Młodzieżowej Olimpiady Informatycznej.
Zadanie. Trzej znajomi: Adam, Błażej i Cezary postanowili napisać ciąg liczb naturalnych. Każdy z nich miał inny pomysł na ciąg. Adam chciał napisać ciąg Błażej ciąg zaś Cezary ciąg Znajomi długo nie mogli dojść do porozumienia, dlatego postanowili zbudować nowy ciąg Ustalili, że na każdej pozycji wybiorą którąś ze swoich opcji, czyli Koledzy zgadzają się, że różnica pomiędzy największym a najmniejszym elementem ciągu powinna być jak najmniejsza. Jaką najmniejszą różnicę może mieć ciąg
Rozwiązanie
Zacznijmy od rozwiązania, które generuje wszystkie możliwe ciągi Takich ciągów jest (wartość każdego z elementów można wybrać na sposoby). Spośród wygenerowanych ciągów należy wybrać ten, który ma najmniejszą różnicę pomiędzy największym a najmniejszym elementem, oraz wypisać tę różnicę. Dla ustalonego ciągu znalezienie najmniejszego i największego elementu można wykonać w czasie (przeglądamy kolejne elementy, pamiętając najmniejszy oraz największy). Rozwiązanie działa w czasie
Obserwacja:
Zauważmy, że dla ustalonych całkowitych możemy w czasie sprawdzić, czy istnieje ciąg którego wartości elementów należą do przedziału Warunkiem koniecznym i wystarczającym jest, aby dla każdego indeksu przynajmniej jeden z trzech elementów należał do
Rozwiązanie
Niech i oznaczają odpowiednio wartość najmniejszego i największego elementu w ciągach i Korzystając z powyższej obserwacji, wystarczy dla wszystkich par liczb całkowitych i sprawdzić, czy istnieje ciąg którego wartości należą do przedziału Spośród poprawnych przedziałów należy wybrać ten o najmniejszej różnicy Wszystkich przedziałów do sprawdzenia jest Zatem rozwiązanie zajmuje czas
Rozwiązanie
Niech będzie zbiorem wartości, które występują przynajmniej raz w ciągu lub Zauważmy, że wystarczy rozważać tylko takie przedziały dla których oraz Moc zbioru jest rzędu (co najwyżej różnych wartości może pojawić się w ponieważ tyle jest w sumie elementów). Stąd do sprawdzenia mamy przedziałów, zatem całkowita złożoność czasowa wynosi
Rozwiązanie
Okazuje się, że nie musimy sprawdzać wszystkich wyżej wymienionych przedziałów. Wystarczy, że dla każdego wyznaczymy takie najmniejsze że istnieje ciąg którego wartości elementów należą do Ustalmy dla którego szukamy najmniejszego Następnie wartość wyszukajmy binarnie w przedziale Rozwiązanie działa w czasie
Rozwiązanie
Podobnie jak wyżej, dla każdego wyznaczymy najmniejsze poprawne W tym celu skonstruujemy ciąg którego największy element będzie możliwie najmniejszy. Dla każdego mamy trzech kandydatów Spośród nich wybieramy najmniejszego, który jest większy lub równy Jeśli taki element nie istnieje, to znaczy, że nie istnieje ciąg z minimalnym elementem W przeciwnym przypadku Dla ustalonego wyznaczenie minimalnego odbywa się w czasie zatem całe rozwiązanie działa w czasie
Rozwiązanie
Każdy z elementów ciągów i opiszmy parą liczb: wartość i indeks. W ten sposób otrzymamy par: Następnie posortujmy te pary rosnąco względem pierwszej współrzędnej, aby otrzymać ciąg Zauważmy, że z ciągu (dla ) można wybrać elementów, które utworzą ciąg jeśli Innymi słowy, dla każdej pozycji (od do ) musimy ustalić przynajmniej jeden element. Zatem chcemy znaleźć takie indeksy że z można zbudować ciąg oraz jest minimalne. Wystarczy, że dla każdego od do znajdziemy najmniejsze takie że z elementów można zbudować ciąg Do rozwiązania tego problemu wykorzystamy metodę gąsienicy. Na początku Dopóki fragment nie pozwala stworzyć poprawnego ciągu, to zwiększamy o jeden. W przeciwnym przypadku przechodzimy do kolejnego W każdym kroku zliczamy liczbę wystąpień każdego indeksu na rozpatrywanym fragmencie oraz pamiętamy liczbę różnych indeksów, które występują przynajmniej raz. Jeśli ta wartość jest równa to wtedy rozpatrywany fragment tworzy ciąg
Sortowanie działa w czasie zaś faza szukania najkrótszych fragmentów dla każdego początku zajmuje czas Zatem całe rozwiązanie działa w czasie