Informatyczny kącik olimpijski
XORanges
W tym odcinku omówimy rozwiązanie zadania XORanges, które pojawiło się na trzecich zawodach European Junior Olympiad in Informatics (Maribor, Słowenia).
Zadanie (XORanges). Dany jest ciąg liczb naturalnych oraz poleceń dwóch typów. 1) Zmień wartość -tego elementu. 2) Podaj współczynnik przedziału Współczynnik przedziału obliczamy w następujący sposób: dla każdego podsłowa (spójnego fragmentu) tego przedziału liczymy xor jego wartości, następnie xorujemy te wyniki, otrzymując współczynnik przedziału. Przykładowo współczynnik przedziału wynosi Zaproponuj algorytm, który jest w stanie możliwie szybko wykonać wszystkie polecenia podane na wejściu.
Na początku przyjmijmy, że polecenia typu będziemy wykonywali w czasie poprzez zmianę wartości Zatem zajmijmy się odpowiedziami na polecenia typu Załóżmy, że chcemy obliczyć współczynnik Na potrzeby artykułu wprowadźmy kilka oznaczeń. Niech:
- oznacza ciąg
- "xor podsłowa " oznacza wartość
Rozwiązanie
Pierwsze rozwiązanie polega na obliczeniu xora każdego z podsłów, gdzie i oznacza długość przedziału Obliczenie xora podsłowa odbywa się za pomocą metody naiwnej, polegającej na przejściu po wszystkich elementach. Na koniec xorujemy powyższe wyniki. Rozwiązanie dla jednego polecenia działa w czasie zatem całkowita złożoność to
Rozwiązanie
W tym rozwiązaniu, podobnie jak wyżej, obliczymy xor podsłów (dla wszystkich ) niezależnie. Jednak tym razem, zamiast naiwnej metody, skorzystamy z obserwacji, że:
gdzie Ciąg ma analogiczną konstrukcję do ciągu sum prefiksowych i możemy go wygenerować w czasie Otóż zaś (dla ). W ten sposób otrzymaliśmy rozwiązanie działające w czasie
Rozwiązanie
Przypomnijmy proste fakty:
- (dla naturalnego),
- (dla naturalnego),
- jest operacją łączną i przemienną.
Na podstawie powyższych faktów możemy zauważyć, że do obliczenia współczynnika przedziału wystarczy znać parzystość liczby wystąpień każdego elementu w wyrażeniu je opisującym. Przykładowo:
gdyż i występują nieparzyście wiele razy w całym wyrażeniu, zaś występuje parzyście wiele razy.
Zastanówmy się, ile razy (dla ) występuje we wzorze opisującym współczynnik przedziału Innymi słowy chcemy obliczyć, w ilu podsłowach występuje Niech oznacza tę wartość. Otóż początkiem takiego podsłowa może być element o numerze z przedziału końcem zaś element o numerze z przedziału
Zatem Współczynnik przedziału to xor zbioru i jest nieparzyste Wyznaczenie tego zbioru realizujemy w czasie Zatem całe rozwiązanie działa w czasie
Rozwiązanie
Przed nami rozwiązanie wzorcowe. Polecenie będziemy wykonywali nieco inaczej niż poprzednio, ale najpierw opiszemy operację
Przeanalizujmy parzystości elementów ciągu Otóż jest nieparzyste, jeśli i są nieparzyste. Stąd jest nieparzyste wtedy i tylko wtedy, gdy są tej samej parzystości. Zatem jeśli i są różnej parzystości, to odpowiedzią jest W przeciwnym przypadku odpowiedzią jest:
Chcemy szybko znajdować wartość powyższego wyrażenia. Zauważmy, że jest to xor elementów na pozycjach parzystych lub nieparzystych ciągu Niech zatem:
Wówczas dla parzystego odpowiedzią jest zaś dla nieparzystego odpowiedzią jest
Zbudujmy dwa drzewa przedziałowe. Liśćmi pierwszego z nich niech będą wartości ciągu zaś liśćmi drugiego niech będą wartości ciągu Pozostałe węzły będą przechowywały xor wartości dzieci. Taka struktura pozwala w czasie znajdować przedziału oraz w tym samym czasie obsługiwać operację zmiany wartości elementu (polecenie typu pierwszego). Zatem całe rozwiązanie działa w czasie