Sunteți pe pagina 1din 9

Altfel de copcei...

ARBORI indexai BINAR focus


Mihai Scoraru
Problema determinrii sumei elementelor unei subsecvene a unui ir ale crui valori se modific n timp real apare destul de des n diferite aplicaii. Ea a aprut, sub diverse forme i la anumite concursuri de programare. n cadrul acestui articol vom prezenta o structur de date care poate fi folosit pentru rezolvarea eficient a acestei probleme. Prin subsecven nelegem un subir ale crui elemente se afl pe poziii consecutive n irul iniial. De exemplu, (2, 3, 4) este o subsecven a irului (1, 2, 3, 4, 5) format din al doilea, al treilea i al patrulea element al irului, n timp ce (1, 2, 4) nu este o subsecven deoarece nu este format din elemente aflate pe poziii consecutive. n cadrul acestui articol vom identifica o subsecven prin extremitile sale (poziia cea mai din stnga i poziia cea mai din dreapta din ir). O subsecven care ncepe n poziia a i se termin n poziia b va fi notat prin <a, b>. Pentru irul (1, 2, 3, 4, 5) subsecvena (2, 3, 4) va fi notat prin <2, 4> dac numerotarea elementelor ncepe cu 1 sau prin <1, 3> dac numerotarea ncepe de la 0. Deseori, avem nevoie de informaii referitoare la subsecvenele unui ir cum ar fi suma elementelor, produsul lor, valoarea minim, valoarea maxim etc. La prima vedere, rezolvarea acestei probleme pare destul de simpl (de exemplu, pentru sum se parcurg elementele subsecvenei i se adun). Totui, acest algoritm este ineficient datorit faptului c necesit parcurgerea ntregii subsecvene. Vom arta c exist algoritmi pentru care o astfel de parcurgere nu este necesar. Totui, dac am efectua o singur dat sau de un numr limitat de ori o astfel de parcurgere, algoritmul ar putea prea performant, viteza de execuie fiind relativ mare. Problema se complic dac elementele irului se modific n timp real. Modificri n timp real S presupunem c exist dou tipuri de operaii care pot fi efectuate asupra unui ir. Primul tip const n modificarea valorii unui element, n timp ce al doilea reprezint interogri (cereri de informaii) referitoare la anumite subsecvene ale irului. De obicei, cele dou tipuri de operaii sunt "amestecate" n sensul c nu vor fi doar modificri urmate din interogri, ci putem avea o modificare, urmat de dou interogri, urmate de cinci modificri, urmate de alte dou interogri etc.

Introducere

Aadar, putem spune c elementele irului se modific n timp real i interogrile se refer la starea curent a irului (cea din momentul cererii de informaii). Enunul problemei n cele ce urmeaz vom prezenta un enun al problemei, particularizat pentru cazul n care interogrile se refer la suma elementelor subsecvenelor. Se consider un ir de numere ntregi care are toate elementele nule. O modificare a unui element const n adunarea unei valori la valoarea curent (pot fi realizate i scderi care au forma adunrii unor valori negative). Pe parcursul modificrilor pot aprea interogri referitoare la suma elementelor unei subsecvene a irului. Problema poate fi enunat n multe alte forme. Una dintre ele ar putea fi urmtoarea: Un furnizor lucreaz cu N distribuitori; n fiecare moment distribuitorii pot efectua pli sau pot cumpra produse. De asemenea, n fiecare moment furnizorul poate cere informaii referitoare la suma total a datoriilor pe care le au magazinele cu numere de ordine cuprinse ntre dou valori date. Evident, exist multe alte enunuri echivalente. De asemenea, pot aprea enunuri n care operaia de nsumare ar putea fi nlocuit cu altele. De exemplu, furnizorul ar putea dori s cunoasc datoria maxim a unui magazin care are numrul de ordine cuprins ntre dou valori date. Exemplu Vom exemplifica acum evoluia n timp real a unui ir format din cinci elemente, prezentnd valorile irului dup fiecare modificare i rezultatul fiecrei interogri. Operaia Iniializare const n setarea la 0 a valorilor tuturor elementelor. Operaia Adun(i, x) const n adunarea valorii x la valoarea curent a celui de-al i-lea element.

GInfo nr. 13/1 - ianuarie 2003

16

Operaia Sum(a, b) furnizeaz suma elementelor subsecvenei <a, b>. Operaie Iniializare Adun(1, 3) Adun(4, 5) Sum(3, 3) Sum(4, 4) Adun(4, 2) Adun(2, 3) Sum(2, 5) Sum(2, 4) Adun(5, 2) Sum(2, 4) Sum(2, 5) Adun(3, 1) Adun(4, -2) Sum(2, 5) Adun(1, -3) Adun(5, 5) Sum(1, 2) Sum(3, 4) Adun(2, -1) Adun(3, 3) Sum(5, 5) Sum(1, 2) Sum(1, 5) ir/Rezultat
0 0 3 0 3 0 0 5 3 0 3 3 10 10 3 3 10 12 3 3 3 3 11 0 3 0 3 3 6 0 2 0 2 7 2 18 0 0 0 0 0 0 0 5 0

citete cod ct timp cod 3 execut dac cod = 1 //modificare atunci scrie Introducei indicele elementului care va fi

modificat:

citete ind scrie Introducei valoarea care va fi adunat

(valoare negativ pentru scderi):

focus

0 7 0 0 7 0

0 7 2

1 7 2 1 5 2 1 5 2 1 5 7

citete val aind aind + val altfel //interogare scrie Introducei extremitile subsecvenei: citete st, dr suma 0 pentru i st, dr execut suma suma + ai sfrit pentru scrie Suma elementelor secvenei este, suma sfrit dac scrie Introducei codul operaiei: citete cod sfrit ct timp

1 5 7 4 5 7

Cazul unidimensional

Din modul n care a fost enunat problema, rezult c operaiile sunt efectuate asupra unui tablou unidimensional; aadar, acesta este cazul unidimensional al problemei. Vom prezenta n continuare trei algoritmi care pot fi folosii pentru rezolvarea problemei i apoi le vom studia performanele. Algoritmul naiv Cea mai intuitiv metod de rezolvare const n pstrarea unui vector cu valorile irului, modificarea lor atunci cnd este necesar i calcularea sumelor n momentul n care apar interogri. Pentru a prezenta algoritmul vom considera c o modificare este codificat prin valoarea 1, iar o interogare prin valoarea 2. Ar fi necesar o a treia operaie (codificat prin 3) care ar indica faptul c nu mai exist modificri sau interogri, deci execuia poate fi ncheiat. Versiunea n pseudocod este prezentat n continuare:
//iniializri scrie Introducei numrul de elemente: citete N //dimensiunea irului pentru i 1, N execut ai 0 //valorile iniiale sunt nule sfrit pentru scrie Introducei codul operaiei:

Se observ c modificrile se efectueaz n timp constant deoarece implic doar accesarea unui element al vectorului i modificarea valorii sale. Datorit faptului c pentru calcularea sumei elementelor unei subsecvene este necesar parcurgerea tuturor elementelor subsecvenei, aceast operaie are ordinul de complexitate O(l), unde l este lungimea subsecvenei. Trebuie observat faptul c algoritmul este acelai dac operaia de nsumare este nlocuit cu o alta (calcularea produsului, stabilirea minimului etc.). Vector de sume Prima ncercare de optimizare const n gsirea unui algoritm mai rapid pentru calcularea sumei elementelor unei subsecvene. O posibilitate relativ simpl este pstrarea unui vector b a crui elemente bi reprezint suma primelor elemente ale irului a. Pentru a gsi suma elementelor unei subsecvene <st, dr> vom efectua o simpl diferen: bdr bst-1. Pentru a calcula sumele pentru subsecvene de forma <1, dr> vom avea nevoie de elementul b0 care va avea ntotdeauna valoarea 0. Astfel, pentru o subsecven de aceast form suma elementelor va fi bdr - b0 = bdr. Aadar, folosind acest artificiu, ordinul de complexitate al unei interogri va fi O(1) pentru c este necesar doar o simpl scdere pentru furnizarea rezultatului. Din nefericire, n momentul efecturii unei modificri pentru elementul i, toate elementele bj pentru care j i i modific valoarea. Ca urmare, operaia de modificare a celui de-al i-lea element nu se mai realizeaz n timp constant, deoarece trebuie modificate N - i + 1 valori. Aadar, ordinul de complexitate devine liniar.

17

GInfo nr. 13/1 - ianuarie 2003

Astfel, am reuit s nlocuim algoritmul liniar de determinare a sumei elementelor unei subsecvene cu un algoritm avnd ordinul de complexitate O(1) cu preul creterii timpului de execuie a algoritmului de modificare de la unul constant la unul liniar. Se observ c nu mai avem nevoie de irul a folosit pentru algoritmul anterior, fiind suficient pstrarea valorilor elementelor irului b. Prezentm versiunea n pseudocod a acestui algoritm, folosind aceleai coduri pentru operaiile efectuate:
//iniializri scrie Introducei numrul de elemente: citete N //dimensiunea irului pentru i 0, N execut bi 0 //valorile iniiale sunt nule sfrit pentru scrie Introducei codul operaiei: citete cod ct timp cod 3 execut dac cod = 1 //modificare atunci scrie Introducei indicele elementului care va fi

modificat:

citete ind scrie Introducei valoarea care va fi adunat

(valoare negativ pentru scderi):

GInfo nr. 13/1 - ianuarie 2003

citete val pentru i ind, N execut bi bi + val sfrit pentru altfel //interogare scrie Introducei extremitile subsecvenei: citete st, dr scrie Suma elementelor secvenei este bdr - bst-1 sfrit dac scrie Introducei codul operaiei: citete cod sfrit ct timp

vectorul de sume este mai performant. Totui, n cazul mediu, ambii algoritmi sunt liniari. n cele ce urmeaz vom prezenta o structur de date care permite efectuarea n timp logaritmic att a modificrilor, ct i a interogrilor. Structura de date pe care o propunem este numit arbore indexat binar. Aadar, vom avea o structur arborescent care va permite efectuarea interogrilor n timp logaritmic n condiiile n care i modificrile se efectueaz n timp logaritmic. Pentru a folosi aceast structur de date, va trebui s considerm c elementele irului sunt numerotate ncepnd cu 1. Arborele va fi pstrat sub forma unui vector c n care fiecare element i va conine suma elementelor subsecvenei <i - 2k + 1, i>, unde k este numrul zerourilor terminale din reprezentarea binar a lui i. Aadar, elementele de pe poziiile impare ale arborelui vor pstra suma elementelor unor subsecvene formate dintr-un singur element (aflat pe o poziie impar n irul a). n elementele de pe poziiile de forma 4 k + 2 (un zero terminal n reprezentarea binar a poziiei) vom pstra suma elementelor unor subsecvene formate din dou elemente. n elementele de pe poziiile de forma 8 k + 4 (dou zerouri terminale n reprezentarea binar a poziiei) vom pstra suma elementelor unor subsecvene formate din patru elemente. n general, dac reprezentarea binar a poziiilor au p zerouri terminale, atunci elementele din arbore vor pstra sume ale elementelor unor subsecvene cu 2p elemente. Vom considera c, la un moment dat, irul (format din 15 elemente) este (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15). Valorile vectorului c (cel care reprezint arborele indexat binar) sunt: Element c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 Poziie
0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

focus

Din nou, algoritmul este acelai dac operaia de nsumare este nlocuit cu o alta (calcularea produsului, stabilirea minimului etc.). Arbore indexat binar Practic, pentru algoritmii anteriori una dintre cele dou operaii se efectueaz n timp constant, n timp ce cealalt se efectueaz n timp liniar. Aadar, dac numrul de modificri este aproximativ egal cu cel al interogrilor, timpul de execuie va fi aproximativ acelai. Dac numrul modificrilor este mult mai mare dect cel al interogrilor, atunci este preferabil folosirea algoritmului naiv. Dac, dimpotriv, numrul interogrilor este mult mai mare dect cel al modificrilor, atunci algoritmul bazat pe

Semnificaie Sum(1, 1) Sum(1, 2) Sum(3, 3) Sum(1, 4) Sum(5, 5) Sum(5, 6) Sum(7, 7) Sum(1, 8) Sum(9, 9) Sum(9, 10) Sum(11, 11) Sum(9, 12) Sum(13, 13) Sum(13, 14) Sum(15, 15)

Valoare
1 3 3 10 5 11

36 9 19 11 42 13 27 15

18

Vom prezenta n continuare modul n care se efectueaz modificrile, exemplificnd pe arborele prezentat anterior. n acest scop, vom modifica valoarea celui de-al doilea element din 2 n 8 (se adun valoarea 6).

Se observ c trebuie modificate toate valorile vectorului c care reprezint sume ale unei subsecvene care conine al doilea element al irului; acestea sunt: c2, c4 i c8. Reprezentrile binare ale acestor trei poziii sunt 0010, 0100 i 1000. Se observ c, fiecare astfel de reprezentare (evident, cu excepia primeia) poate fi obinut din cea anterioar prin adunarea valorii 2r, unde r reprezint numrul de zerouri terminale ale reprezentrii binare a poziiei anterioare. Aadar, ar trebui s efectum astfel de adunri pn n momentul n care poziia obinut este mai mare dect dimensiunea irului i s cretem cu 6 valorile tuturor elementelor de pe poziiile de la fiecare pas. Vom exemplifica procedeul i pentru al treilea element. Prima poziie este 0011; numrul zerourilor terminale este 0, deci vom aduna valoarea 20 = 1. Noua poziie va fi 3 + 1 = 4, deci am ajuns la poziia 4 a crei reprezentare binar este 0100. Numrul zerourilor terminale este 2, deci vom aduna valoarea 22 = 4, poziia devenind 4 + 4 = 8. Reprezentarea binar este 1000, deci avem trei zerouri terminale. Valoarea adunat va fi 23 = 8, deci ajungem n poziia 8 + 8 = 16, aadar am depit dimensiunea irului. Se observ c elementele c3, c4 i c8 sunt cele a cror valoare depinde de valoarea elementului de pe a treia poziie. Algoritmul care realizeaz operaia de modificare este urmtorul: Se identific poziia elementului care trebuie modificat. Ct timp poziia curent este cel mult egal cu dimensiunea irului: Se modific valoarea elementului de pe poziia curent. Se determin numrul k al zerourilor terminale din reprezentarea binar a poziiei curente. Noua poziie se determin adunnd valoarea 2k la poziia curent. Se observ c numrul elementelor modificate este cel mult egal cu numrul cifrelor reprezentrii binare a numrului de elemente din ir, deci operaia are ordinul de complexitate O(log N). Mai trebuie prezentat modul n care este efectuat operaia de interogare. Vom ncerca s aplicm o metod similar celei propuse n cazul algoritmului care folosete un vector de sume. Pentru aceasta, dac dorim s determinm suma elementelor subsecvenei <st, dr>, vom determina sumele elementelor subsecvenelor <1, st - 1> i <1, dr>, efectund apoi o simpl diferen. Operaiile efectuate sunt, oarecum, inversele celor de la operaia de modificare. Vom porni din poziia dat i, la fiecare pas, vom determina urmtoarea poziie scznd valoarea 2k unde k reprezint numrul zerourilor terminale din reprezentarea binar a poziiei curente. Ne vom opri n momentul n care poziia curent devine 0. De exemplu, pentru a determina suma elementelor subsecvenei <1, 11> vom porni din poziia 11 a crei reprezentare binar este 1011. Numrul zerourilor terminale

este 0, deci vom scdea valoarea 20 = 1, ajungnd n poziia 11 - 1 = 10. Reprezentarea binar a acesteia este 1010, deci numrul zerourilor terminale este 1. Valoarea sczut este 21 = 2, deci se ajunge n poziia 10 - 2 = 8, a crei reprezentare binar este 1000. De data aceasta avem trei zerouri terminale, deci vom scdea valoarea 23 = 8 ajungnd n poziia 8 - 8 = 0. Aadar, am "trecut" prin poziiile 11, 10 i 8. Adunnd valorile elementelor corespunztoare (c11, c10 i c8) obinem 11 + 19 + 36 = 66, adic exact valoarea cutat. Este uor de observat c c11 reprezint suma elementelor subsecvenei <11, 11>, c10 reprezint suma elementelor subsecvenei <9, 10>, iar c8 reprezint suma elementelor subsecvenei <1, 8>, aadar, n momentul calculrii sumei, fiecare element de pe o poziie mai mic sau egal cu 11 este adunat o singur dat. Pentru a determina suma elementelor unei subsecvene de forma <1, dr> vom folosi urmtorul algoritm: Se identific elementul de pe poziia dr. Ct timp poziia curent este diferit de 0: Se adun la suma total valoarea elementului de pe poziia curent. Se determin numrul k al zerourilor terminale din reprezentarea binar a poziiei curente. Noua poziie se determin scznd valoarea 2k din poziia curent. Evident, pentru a determina suma elementelor unei subsecvene de forma <st, dr> vom aplica de dou ori algoritmul prezentat: o dat pentru subsecvena <1, dr> i o dat pentru subsecvena <1, st-1>, efectund la final diferena valorilor obinute. De exemplu, pentru determinarea sumei elementelor subsecvenei <4, 13> vom calcula mai nti sumele elementelor subsecvenelor <1, 13> i <1, 3>. Acestea sunt Sum(1, 13) = c13 + c12 + c8 = 13 + 42 + 36 = 91 i Sum(1, 3) = c3 + c2 = 3 + 3 = 6, diferena lor fiind 91 - 6 = 85 care este egal cu valoarea Sum(4, 13). Se observ c numrul elementelor adunate este cel mult egal cu numrul cifrelor reprezentrii binare a poziiei elementului dat, deci operaia are ordinul de complexitate O(log N). Din nou, se observ c nu avem nevoie de pstrarea elementelor irului a, fiind suficient pstrarea valorilor vectorului c (cel care reprezint arborele indexat binar). Varianta n pseudocod a algoritmului de rezolvare a problemei folosind un arbore indexat binar este urmtoarea:
//iniializri scrie Introducei numrul de elemente: citete N //dimensiunea irului pentru i 0, N execut ci 0 //valorile iniiale sunt nule sfrit pentru

focus
19
GInfo nr. 13/1 - ianuarie 2003

scrie Introducei codul operaiei: citete cod ct timp cod 3 execut dac cod = 1 //modificare atunci scrie Introducei indicele elementului care va fi

modificat:

focus

citete ind scrie Introducei valoarea care va fi adunat

(valoare negativ pentru scderi):

st st - 2poz poz poz + 1 sfrit ct timp scrie Suma elementelor subsecvenei este: s1 s2 sfrit dac scrie Introducei codul operaiei: citete cod sfrit ct timp

20

citete val poz 0 //poziia celui mai nesemnficativ bit cu //valoarea 1 ct timp ind N execut cind cind + val ct timp ind & 2poz 0 execut //& reprezint operaia de conjucie //logic (I-logic) poz poz + 1 sfrit ct timp ind ind + 2poz poz poz + 1 //valoarea poz este incrementat //i nu reiniializat cu 0 deoarece //tim c acum avem cel puin //poz + 1 zeroruri terminale, prin //adunare adugndu-se cel puin //un zero terminal sfrit ct timp altfel //interogare scrie Introducei extremitile subsecvenei: citete st, dr //calcularea primei sume s1 0 //iniializare poz 0 //poziia celui mai nesemnficativ bit cu //valoarea 1 ct timp dr > 0 execut s1 s1 + cdr ct timp dr & 2poz = 0 execut poz poz + 1 sfrit ct timp dr dr - 2poz poz poz + 1 //prin scdere se adaug cel //puin un zero terminal sfrit ct timp //calcularea celei de-a doua sume st st - 1 //trebuie calculat valoarea pentru //st-1 s2 0 //iniializare poz 0 //poziia celui mai nesemnficativ bit cu //valoarea 1 ct timp st > 0 execut s2 s2 + cst ct timp st & 2poz = 0 execut poz poz + 1 sfrit ct timp

i de data aceasta putem nlocui operaia de nsumare cu alte operaii (nmulire, minim, maxim etc.).

Cazul bidimensional

Problema enunat poate fi modificat astfel nct s lucrm n spaiul bidimensional. Enunul noii probleme ar putea fi urmtorul: Se consider o matrice de numere ntregi care are toate elementele nule. O modificare a unui element al matricei const n adunarea unei valori la valoarea curent (pot fi realizate i scderi care au forma adunrii unor valori negative). Pe parcursul modificrilor pot aprea interogri referitoare la suma elementelor unei submatrice. Aadar, n acest caz, interogrile se refer la suma valorilor dintr-o "zon dreptunghiular" care face parte din matrice. Evident, pentru reprezentarea datelor vom folosi tablouri bidimensionale n locul celor unidimensionale (matrice n locul vectorilor). Din nou, enunul poate fi reformulat n diferite moduri. O variant ar putea fi: Se consider un teren de form dreptunghiular avnd lungimea M i limea N. Terenul este mprit n regiuni de form ptrat avnd latura egal cu unitatea. n fiecare moment, ntr-o anumit regiune pot fi plantai sau tiai pomi. De asemenea, n fiecare moment proprietarul terenului ar putea cere informaii referitoare la numrul total al pomilor care se afl ntr-o regiune dreptunghiular a terenului. Vom adapta cei trei algoritmi descrii pentru cazul unidimensional pentru a rezolva noua problem i vom studia apoi performanele acestora. De data aceasta, pentru operaia de modificare vom avea nevoie de doi parametri care vor reprezenta linia i coloana pe care se afl elementul a crui valoare va fi modificat. Pentru interogri vom avea nevoie de patru parametri care vor reprezenta coordonatele colurilor din stnga-sus i dreapta-jos ale unui dreptunghi. Vom exemplifica acum cazul bidimensional al problemei folosind o matrice cu trei linii i trei coloane.

GInfo nr. 13/1 - ianuarie 2003

Operaie Iniializare Adun(2, 2, 3) Adun(1, 3, 5) Sum(2, 1, 3, 3) Adun(2, 1, 1) Sum(1, 2, 2, 3) Adun(2, 2, -1) Sum(1, 2, 2, 3) Adun(2, 2, 5) Adun(2, 2, -5) Adun(3, 2, 4) Sum(1, 1, 3, 3)

Matrice/Rezultat
0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 3 0 0 3 0 0 1 3 0 0 8 0 0 1 2 0 0 7 0 0 1 7 0 0 0 0 1 2 0 0 0 0 1 2 0 4 12 0 0 0 0 0 0 5 0 0 5 0 0 5 0 0 5 0 0 5 0 0 5 0 0

citete val aindx,indy aindx,indy + val altfel //interogare scrie Introducei coordonatele colurilor: citete st, sus, dr, jos suma 0 pentru i sus, jos execut pentru j st, dr execut suma suma + aij sfrit pentru sfrit pentru scrie Suma elementelor dreptunghiului este: suma sfrit dac scrie Introducei codul operaiei citete cod sfrit ct timp

focus

Modificrile se efectueaz tot n timp constant deoarece implic doar accesarea unui element al matricei i modificarea valorii sale. Datorit faptului c pentru calcularea sumei elementelor dintr-un dreptunghi este necesar parcurgerea tuturor elementelor dreptunghiului, aceast operaie are ordinul de complexitate O(l h), unde l i h sunt lungimile laturilor dreptunghiului. Matrice de sume Adaptarea algoritmului care folosete un vector de sume este destul de simpl. Vom pstra o matrice b ale creia elemente bij vor conine sumele corespunztoare dreptunghiurilor cu colul din stnga-sus n poziia (1, 1) i cel din dreapta-jos n poziia (i, j). Studiind figura alturat, este uor de observat c pentru a calcula valoarea Sum(st, sus, dr, jos) poate fi folosit relaia: Sum(st, sus, dr, jos) = Sum(1, 1, dr, jos) Sum(1, 1, st - 1, jos) Sum(1, 1, dr, sus - 1) + Sum(1, 1, st - 1, sus - 1). Se observ c prin scderea valorii Sum(1, 1, st-1, jos) se scad valorile tuturor elementelor aflate la dreapta dreptunghiului considerat, iar prin scderea valorii Sum(1, 1, dr, sus-1) se scad valorile elementelor aflate deasupra dreptunghiului. Aceste operaii implic scderea de dou ori a tuturor elementelor aflate la stnga i deasupra dreptunghiului considerat, motiv pentru care va trebui s adunm valoarea Sum(1, 1, st-1, sus-1). Folosind acest artificiu avem nevoie de accesarea a patru elemente ale matricei b, deci operaia se realizeaz n timp constant.

Algoritmul naiv Primul algoritm descris pentru cazul unidimensional poate fi adaptat foarte uor pentru a rezolva cazul bidimensional al problemei. Vom pstra valorile matricei, le vom modifica dac este necesar i vom calcula sumele cerute de interogri. Versiunea n pseudocod este prezentat n continuare:
//iniializri scrie Introducei dimensiunile matricei: citete M, N pentru i 1, M execut pentru j 1, N execut aij 0 //valorile iniiale sunt nule sfrit pentru sfrit pentru scrie Introducei codul operaiei: citete cod ct timp cod 3 execut dac cod = 1 //modificare atunci scrie Introducei indicii elementului care va fi

GInfo nr. 13/1 - ianuarie 2003

modificat:

citete indx, indy scrie Introducei valoarea care va fi adunat

(valoare negativ pentru scderi):

21

focus

Din nou, n momentul modificrii valorii unui element de coordonate (x, y), va trebui s modificm valorile tuturor elementelor matricei b de coordonate (i, j) pentru care i x i j y. Aadar, vom modifica (M - x + 1) (N - y + 1) elemente, ordinul de complexitate devenind O(M N). Pentru a putea determina valori pentru dreptghiuri n care colul din stnga-sus are una dintre coordonate egal cu 1 va trebui s considerm c valorile elementelor matricei sunt nule dac cel puin unul dintre cei doi indici este 0. Prezentm versiunea n pseudocod a algoritmului descris:
//iniializri scrie Introducei dimensiunile matricei: citete M, N //dimensiunea irului pentru i = 0, M execut pentru i = 0, N execut bij = 0 //valorile iniiale sunt nule sfrit pentru sfrit pentru scrie Introducei codul operaiei: citete cod ct timp cod 3 execut dac cod = 1 //modificare atunci scrie Introducei indicii elementului care va

Pentru a rezolva problema vom crea un arbore de arbori indexai binar. Aadar, vom avea o matrice c ale crei elemente cij vor reprezenta sumele elementelor din dreptunghiul care are colul din stnga-sus n poziia (i - 2k + 1, j - 2l + 1), iar cel din dreapta-jos n poziia (i, j). Valoarea k reprezint numrul zerourilor terminale din reprezentarea binar a lui i, iar l reprezint numrul zerourilor terminale din reprezentarea binar a lui j. De exemplu, pentru matricea:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

elementele arborelui de arbori indexai binar vor avea urmtoarele semnficaii:


Sum(1, 1, 1, 1) Sum(1, 1, 1, 2) Sum(1, 3, 1, 3) Sum(1, 1, 1, 4) Sum(1, 1, 2, 1) Sum(1, 1, 2, 2) Sum(1, 3, 2, 3) Sum(1, 1, 2, 4) Sum(3, 1, 3, 1) Sum(3, 1, 3, 2) Sum(3, 3, 3, 3) Sum(3, 3, 3, 4) Sum(1, 1, 4, 1) Sum(1, 1, 4, 2) Sum(1, 3, 4, 3) Sum(1, 1, 4, 4)

fi modificat:

Aadar, valorile matricei care reprezint arborele binar vor fi:


1 3 3 6 6 14 10 36 9 19 11 23 28 60 36 136

citete indx, indy scrie Introducei valoarea care va fi adunat

(valoare negativ pentru scderi):

GInfo nr. 13/1 - ianuarie 2003

citete val pentru i indx, M execut pentru i indy, N execut bij bij + val sfrit pentru sfrit pentru altfel //interogare scrie Introducei coordonatele colurilor: citete st, sus, dr, jos scrie Suma elementelor secvenei este: bdr,jos bst-1,jos - bdr,sus-1 + bst-1,sus-1. sfrit dac scrie Introducei codul operaiei citete cod sfrit ct timp

Din nou, algoritmul este foare asemntor dac operaia de nsumare este nlocuit cu o alta (calcularea produsului, stabilirea minimului etc.). Arbore de arbori indexai binar Din nou, avem doi algoritmi n care una dintre operaii este eficient, n timp ce cealalt necesit un timp de execuie mai mare. Folosind arborii indexai binar, vom putea gsi algoritmi care realizeaz ambele operaii ntr-un timp de ordinul O(log M log N), unde M i N sunt dimensiunile matricei.

22

S presupunem c trebuie s modificm valoarea elementului de coordonate (2, 1) care face parte dintr-o matrice cu 8 linii i 4 coloane. Vom aplica de dou ori principiul descris pentru cazul unidimensional. Vom identifica linia i pe care se afl elementul i vom efectua modificri n toate coloanele de pe acea linie n care acestea trebuie efectuate. Pentru aceasta vom identifica coloana j, vom determina numrul k al zerourilor terminale i apoi vom aduna la j valoarea 2k. Ajungem ntr-o nou poziie i continum procedeul pn n momentul n care valoarea coloanei curente depete numrul de coloane al matricei. n acest moment vom determina numrul zerourilor terminale l din reprezentarea binar a valorii i i ne vom "muta" pe linia i + 2l. Vom reveni la coloana j i vom parcurge aceeai pai ca i la linia anterioar. Vom continua pn n momentul n care valoarea liniei curente va fi mai mare dect numrul de linii ale matricei. Pe fiecare linie vom modifica cel mult log2N elemente; n plus, vom modifica elemente de pe cel mult log2M linii, aadar, ordinul de complexitate al operaiei de modificare a unui element este O(log M log N). Ca urmare, dac se modific elementul de coordonate (3, 1), atunci vor trebui modificate urmtoarele elemente

ale matricei care reprezint arborele de arbori indexai binar: c31, c32, c34, c41, c42, c44, c81, c82 i c84. n cazul n care dorim s efectum o interogare vom folosi aceeai metod. Singura diferen este, din nou, faptul c valorile de forma 2k sunt sczute n loc s fie adunate. Datorit faptului c, de data aceasta, avem nevoie de patru sume pentru a furniza rezultatul, algoritmul va fi aplicat de patru ori. Ordinul de complexitate al algoritmului va fi O(log M log N). Vom prezenta n continuare versiunea n pseudocod a algoritmului de rezolvare a problemei n cazul bidimensional, folosind un arbore de arbori indexai binar.
scrie Introducei dimensiunile matricei: citete M, N pentru i 0, M execut pentru j 0, N execut cij 0 //valorile iniiale sunt nule sfrit pentru sfrit pentru scrie Introducei codul operaiei citete cod ct timp cod 3 execut dac cod = 1 //modificare atunci scrie Introducei indicii elementului care va fi

//iniializri

modificat:

citete indx, indy scrie Introducei valoarea care va fi adunat

(valoare negativ pentru scderi):

citete val pozi 0 ct timp indx M execut pozj 0 j indy ct timp j N execut cindx,j cindx,j + val ct timp indx & 2pozj = 0 execut pozj pozj + 1 sfrit ct timp j j + 2pozj pozj pozj + 1 sfrit ct timp ct timp indx & 2pozi = 0 execut pozi pozi + 1 sfrit ct timp indx indx + 2pozi pozi pozi + 1 sfrit ct timp altfel //interogare scrie Introducei coordonatele colurilor: citete st, sus, dr, jos //calcularea primei sume s0 x jos

y dr pozi 0 ct timp x 0 execut pozj 0 jy ct timp y 0 execut s1 s1 + cx,j ct timp x & 2pozj = 0 execut pozj pozj + 1 sfrit ct timp j j - 2pozj pozj pozj + 1 sfrit ct timp ct timp x & 2pozi = 0 execut pozi pozi + 1 sfrit ct timp x x - 2pozi pozi pozi + 1 sfrit ct timp s1 s s0 //calcularea celei de-a doua sume x jos y st - 1 ... //se aplic exact aceeai secven s2 s s0 //calcularea celei de-a treia sume x sus - 1 y dr ... //se aplic din nou exact aceeai secven s3 s s0 //calcularea celei de-a patra sume x sus - 1 y dr - 1 ... //se aplic din nou exact aceeai secven s4 s scrie Suma elementelor dreptunghiului este s1 - s2 - s3 + s4 sfrit dac scrie Introducei codul operaiei: citete cod sfrit ct timp

focus
GInfo nr. 13/1 - ianuarie 2003

Cazul tridimensional

Problema enunat poate fi modificat astfel nct s lucrm n spaiul tridimensional. Enunul ar putea fi urmtorul: Se consider un tablou tridimensional care conine numere ntregi i toate elementele sale sunt nule. O modificare a unui element al tabloului const n adunarea unei valori la valoarea curent (pot fi realizate i scderi care au forma adunrii unor valori negative). Pe parcursul modificrilor pot aprea interogri referitoare la suma elementelor unui subtablou "paralelipipedic" .

23

Aadar, n acest caz, interogrile se refer la suma valorilor dintr-o "zon paralelipipedic" a tabloului. Evident, pentru reprezentarea datelor vom folosi tablouri tridimensionale. i acest enun poate fi reformulat n diferite moduri. O variant ar putea fi: O zon a spaiului este reprezentat de un paralelipiped format din cuburi cu latura egal cu unitatea. Dimensiunile paralelipipedului sunt M, N i P. n fiecare sector (cub) pot sosi sau pleca nave spaiale. De asemenea, n fiecare moment amiralul flotei poate cere informaii referitoare la numrul total de nave spaiale dintr-o regiune paralelipipedic din aceast zon a spaiului. Nu vom mai prezenta pe larg cele trei tipuri de algoritmi; vom face doar cteva precizri care ne vor ajuta s generalizm problema pentru spaii n-dimensionale. n primul rnd, n fiecare poziie n care algoritmii pentru cazul bidimensional conineau dou cicluri imbricate, pentru algoritmii care rezolv cazul tridimensional vom avea trei cicluri. Ca urmare, ordinul de complexitate al primilor doi algoritmi va deveni O(M N P). Ordinul de complexitate al celui de-al treilea algoritm va fi O(log M log N log P). n al doilea rnd, elementele tabloului tridimensional vor fi identificate prin trei indici. Aadar, pentru o modificare vom avea nevoie de trei parametri "geometrici", iar pentru o interogare de ase astfel de parametri. n al treilea rnd, pentru ultimii doi algoritmi va trebui s calculm opt sume n loc de patru. Formula de calcul va fi urmtoarea: Sum(x1, y1, z1, x2, y2, z2) = Sum(1, 1, 1, x2, y2, z2) Sum(1, 1, 1, x1 - 1, y2, z2) Sum(1, 1, 1, x2, y1 - 1, z2) Sum(1, 1, 1, x2, y2, z1 - 1) + Sum(1, 1, 1, x1 - 1, y1 - 1, z2) + Sum(1, 1, 1, x1 - 1, y2, z1 - 1) + Sum(1, 1, 1, x2, y1 - 1, z1 - 1) Sum(1, 1, 1, x1 - 1, y1 - 1, z1 - 1) Mai precizm faptul c pentru cel de-al treilea algoritm vom folosi un tablou tridimensional care va reprezenta un arbore de arbori de arbori indexai binar. Toate celelalte aspecte ale celor trei algoritmi descrii pot fi adaptate foarte simplu pentru a rezolva problema tridimensional.

la valoarea curent (pot fi realizate i scderi care au forma adunrii unor valori negative). Pe parcursul modificrilor pot aprea interogri referitoare la suma elementelor unui subtablou. Aadar, n acest caz, interogrile se refer la suma valorilor dintr-o "zon n-dimensional" a tabloului. Evident, pentru reprezentarea datelor vom folosi tablouri n-dimensionale. De data aceast, cele dou cicluri imbricate din algoritmii pentru cazul bidimensional (cele trei din algoritmii pentru cazul tridimensional) vor fi nlocuite de n cicluri imbricate. Ca urmare, ordinul de complexitate al primilor doi algoritmi va depinde de produsul celor n dimensiuni, iar ordinul de complexitate al celui de-al treilea algoritm va depinde de produsul logaritmilor celor n dimensiuni. Evident, vom avea acum n parametri "geometrici" pentru o modificare i 2 n parametri de acest tip pentru o interogare. Numrul sumelor care trebuie calculate pentru o interogare (la al doilea i al treilea algoritm) este, pentru cazul general, 2n. innd cont de aceste observaii, algoritmii prezentai pot fi folosii pentru rezolvarea unor probleme de acest tip n care numrul dimensiunilor este orict de mare.

focus

Concluzii

GInfo nr. 13/1 - ianuarie 2003

n cadrul acestui articol am prezentat o structur de date care permite rezolvarea eficient a unei categorii de probleme. Pentru a evidenia performanele algoritmilor care folosesc o astfel de structur de date, am prezentat i alte dou categorii de algoritmi, mult mai uor de implementat, dar ineficieni. De asemenea, am prezentat modul n care pot fi generalizai algoritmii folosii pentru cazul cel mai simplu (cel unidimensional) pentru a rezolva problema pentru cazuri n care numrul dimensiunilor este orict de mare. Am exemplificat algoritmii pentru cazul n care interogrile se refer la suma anumitor elemente. Cu toate acestea este evident faptul c, n cazul tuturor acestor algoritmi, aceast operaie poate fi nlocuit cu altele (produsul elementelor, minimul sau maximul lor etc.). 1. J. Nummenmaa, E. Mkinen, I. Aho, IOI '01 Competition, Tampere, Finland, 2001 2. P. M. Fenwick, A new data structure for cumulative frequency tables, Software-Practice and Experience, vol. 24, no. 3, p. 327-336, 1994 3. T. H. Cormen, C. E. Leiserson, R. R. Rivest, Introducere n algoritmi, Computer Libris Agora, Cluj-Napoca, 2000

Bibliografie

Cazul n-dimensional

Vom generaliza acum problema pentru a putea fi enunat ntr-un spaiu cu un numr orict de mare de dimensiuni. O variant a enunului este: Se consider un tablou n-dimensional care conine numere ntregi i toate elementele sale sunt nule. O modificare a unui element al tabloului const n adunarea unei valori

24

Mihai Scoraru este redactor-ef al GInfo. Poate fi contactat prin e-mail la adresa skortzy@yahoo.com.