You are on page 1of 9

Pierwiastki

Sumy na przedziale
Wersja statyczna sumy prefiksowe
Wersja dynamiczna:
Dodajemy w punkcie warto i pytamy o sum na
caym przedziale.
Czyli inaczej mwic mamy tablic T[1..n] na ktrej
chcemy dokonywa operacji dodania wartoci v w
punkcie a oraz zapytania o sum na przedziale
[a..b], operacji jest cznie m.
Sumy na przedziale
Rozwizanie brutalne
Wstawianie: Suma:
void insert(int a, int v) { int suma(int a, int b) {
T[a] +=v; int wynik = 0;
} for(int i = a; i <= b; i++)
wynik+=T[i];
return wynik;
Zoono staa
}
Zoono zalena od dugoci
przedziau, czyli w najgorszym
wypadku nawet O(n)

Czyli wykonanie m operacji moe mie zoono O(n*m)


Sumy na przedziale
Jak to zrobi szybciej?
Pomys dzielimy cao na n kubekw, kady dugoci n i trzymamy
w drugiej tablicy (S[]) sum dla caego kubeka.
Jak to teraz dziaa?
Przy wstawianiu oprcz dodawa do tablicy T[a] aktualizujemy take warto
S[a/n] odpowiadajc za cay kubeek.
Przy zapytaniu dzielimy przedzia na kubeki, ktre w caoci on pokrywa, a dla
kubekw skrajnych, ktre ten przedzia przecina przegldamy wszystkie punkty.

Dla zapytania o przedzial [2..14]


S[] 17 14 11 19
0 1 2 3
T[] 2 5 2 8 3 5 1 5 2 2 5 2 3 4 5 7
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Sumy na przedziale
Jaka zoono?
Operacja wstawiania nadal zajmuje czas stay
Przy zapytaniu:
Przejrzymy co najwyej n kubekw, bo tyle ich
maksymalnie moe by
Dla skrajnych kubekw przejrzymy co najwyej liniowo
wiele punktw, ale wzgldem wielkoci kubeka, czyli n
Zatem sumaryczna zoono operacji zapytania to
O(n)
Czyli m operacji bdzie miao zoono co najwyej
O(m*n)
Sumy na przedziale
Kody funkcji: (sq = n)
Wstawianie:
void insert(int a, int v) {
T[a]+=v;
S[a/sq]+=v;
}
Sumy na przedziale
Kody funkcji: (sq = n)
Suma:
int suma(int a, int b) {
int ka = a/sq, kb = b/sq, wynik = 0;
for(int i = ka+1; i <= kb-1; i++) wynik+=S[i];
//a i b mog by w jednym kubeku, std ten min(...) oraz if(...)
for(int i = a; i <= min(b, (ka+1)*sq -1); i++) wynik+=T[i];
if(ka != kb) Ostatni element kubeka
for(int i = kb*sq; i <= b; i++) wynik+=T[i];
return wynik; Pierwszy element kubeka
}
Dodajemy sumy z kubekw
ka kb
S[] 17 14 11 19
0 1 2 3
T[] 2 5 2 8 3 5 1 5 2 2 5 2 3 4 5 7
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Suma z kubeka gdzie jest a Suma z kubeka gdzie jest b


Jakie jeszcze mog by zapytania
maksimum/minumum na przedziale
Inne operacje, ktre s czne (jeli nie s
przemienne to trzeba bdzie troche
pokombinowa)
Ale te mona wykonywa operacj na
przedziale i pyta o warto w punkcie
Lub mona wstawia na przedziale i pyta o
warto na przedziale (co ciekawszego)
Przedzia - punkt
Wstawienie:
void insert(int a, int b, int v) {
int ka = a/sq, kb = b/sq;
for(int i = ka+1; i <= kb-1; i++) S[a] += v;
for(int i = a; i <= min(b, (ka+1)*sq-1); i++) T[a] += v;
if(ka != kb)
for(int i = kb*sq; i <= b; i++) T[a]+=v;
}
Odczytanie wartoci:
int value(int a) {
return T[a] + S[a/sq];
}

You might also like