Podstawy Programowania
Złożoność obliczeniowa
Sumy prefiksowe
Podaj sumę na przedziale ciągu o długości
Pierwsze rozwiązanie, na jakie możemy wpaść to przejrzenie wszystkich elementów od -tego do -tego i zsumowanie ich. Tak po prostu. Bez haczyków. Zastanówmy się, jaką to ma złożoność obliczeniową. Wykonamy operacji. W najgorszym wypadku, kiedy i wyniesie ona Co gdybyśmy chcieli zapytać się o sumę na przedziale razy? Uzyskalibyśmy wtedy złożoność co zdecydowanie nie brzmi satysfakcjonująco.
Niech oznacza sumę na prefiksie o długości (inaczej -tym prefiksie). Chcemy obliczyć dla każdego naturalnego Pomogą nam w tym dwa spostrzeżenia:
=
Dla zachodzi:
Pozwala nam to policzyć wszystkie sumy prefiksowe w
Zauważmy, że suma na przedziale to nic innego jak (przy czym zakładamy, że ).
Oznacza to, że jeśli obliczymy wcześniej sumy prefiksowe w to będziemy mogli pytać się o sumy na przedziale w Nasz problem będziemy mogli rozwiązać w zamiast Jest to bardzo satysfakcjonujące rozwiązanie.
Dany mamy prostokąt podzielony na komórki, w każdej znajduje się liczba. Chcemy podać sumę liczb w podprostokątach.
Do rozwiązania tego problemu możemy policzyć coś bardzo podobnego do standardowych sum prefiksowych. Jako oznaczmy sumę w prostokącie, którego lewy górny róg ma współrzędne a prawy dolny Tak samo, jak ostatnio, skorzystamy z tych samych dwóch spostrzeżeń:
Zauważmy, że suma w prostokącie, którego lewy górny róg ma współrzędne a prawy dolny to nic innego jak (zakładamy tutaj, że oraz dla dowolnego ).
Metodę sum prefiksowych możemy rozszerzyć na większą liczbę wymiarów, obliczając odpowiednie wzory podobnie do tych pokazanych powyżej. Jednak już dla jest to dosyć trudne, przez co raczej rzadko widywane.
Funkcja sumy nie jest jedyną funkcją, którą możemy liczyć na prefiksach. Możemy liczyć też chociażby funkcje czy Jednak by móc w ten sposób obliczać ich wartość dla dowolnych przedziałów, używana funkcja musi mieć zdefiniowaną odwrotność (np. odejmowanie dla dodawania, dzielenie dla mnożenia czy dla -a). Dlatego mając tablicę -ów prefiksowych możemy obliczyć na dowolnym przedziale będzie on równy ponieważ funkcją odwrotną dla -a jest właśnie Nie możemy natomiast obliczyć na przedziale mając tylko wartości dla prefiksów, ponieważ funkcja nie ma swojej odwrotności.
Z pewnych względów elementy naszej tablicy numerowaliśmy od jedynki zamiast od zera. Ten trick implementacyjny warto stosować w swoich programach. Pomyślmy, co stanie się, gdy ktoś zapyta nas o prefiks Gdybyśmy indeksowali elementy od zera odpowiedź na nie byłaby równa co spowoduje odwołanie się do elementu będącego poza tablicą. Problem nie będzie występować w przypadku numerowania ciągu od jedynki. W należy zapisać tzw. element neutralny wykonywanego działania (np. 0 dla dodawania, 1 dla mnożenia). Problemy wielowymiarowe są analogiczne.