Omówienie zadania Prawnicy (I etap XXV OI)
W zadaniu mamy dane
Najprostsze podejście
Skoro interesuje nas najlepszy podzbiór
Co możemy się z tego dowiedzieć?
Zastanówmy się, gdzie znajduje się początek, a gdzie koniec przecięcia przedziałów, jeżeli jest ono niepuste. Początek znajduje się tam, gdzie najpóźniejszy początek spośród rozpatrywanych przedziałów. Koniec analogicznie, lecz tym razem interesuje nas najwcześniejszy spośród końców przedziałów.
Czy pomaga nam to w zredukowaniu liczby operacji?
Okazuje się, że bardzo. Mianowicie, powyższy fakt mówi nam, że zarówno liczba początków, jak i liczba końców przedziału wynikowego jest z góry ograniczona przez
Rozwiązanie wielomianowe
Dla każdego przedziału będącego kandydatem (opisanego przez początek jakiegoś przedziału i koniec potencjalnie innego), jeżeli na spotkaniu może być co najmniej
Dalsze optymalizacje
Chcielibyśmy jeszcze bardziej zredukować liczbę kandydatów. Zadajmy sobie w tym momencie ważne pytanie – ile potencjalnych końców musimy rozpatrywać dla założonego początku? Aby odpowiedzieć na to pytanie, na początku zobaczmy, że interesują nas jedynie końce tych przedziałów, których początki znajdują się nie później niż założony początek. Spójrzmy więc na te końce w kolejności niemalejącej. Zauważmy, że im dalszy koniec rozpatrujemy, tym mniej prawników mamy do dyspozycji do naszego spotkania (kolejni prawnicy przestają być dostępni).
Wróćmy więc do naszego pytania. Jeżeli wraz z rozważaniem coraz dalszych końców, liczba prawników do dyspozycji maleje, to interesuje nas dokładnie jeden koniec! Ten, dla którego liczba prawników do dyspozycji jest równa dokładnie
Znajdywanie optymalnego końca
Pozostało nam jedynie zaimplementować nasze rozwiązanie. Przeglądając początki przedziałów w kolejności rosnącej, możemy trzymać w pamięci std::set
w języku C++. Osiągamy zatem złożoność czasową
Opis przygotowano w ramach projektu "Mistrzostwa w Algorytmice i Programowaniu - Uczniowie" - zadania finansowanego ze środków Ministerstwa Cyfryzacji.
![]() |
![]() |
![]() |
![]() |
![]() |