•florin.elfus
Strain
Karma: 109
Deconectat
Mesaje: 43
|
 |
« Răspunde #3 : Martie 27, 2014, 16:54:12 » |
|
Pentru inceput sa zicem ca rezolvi fiecare query independent. Trebuie sa alegi un drum astfel incat valoarea minima a drumului intre (x1, y1) si (x2, y2) sa fie maxima. Sa zicem ca valoarea minima a unui drum este X. Atunci exista un drum intre (x1, y1) si (x2, y2) cu toate valorile >= X. Observi ca daca exista un drum cu toate valorile >= X, va exista un drum cu toate valorile >= X - 1. Asa ca pentru a afla maximul, poti folosi cautarea binara. E important sa folosesti cautarea binara a lui Patrascu, cu puteri ale lui 2.
Cum determini daca o valoare X e buna ca raspuns? O solutie posibila (care va ajuta la cautarea binara in paralel) este sa consideri initial fiecare celula ca fiind o multime disjuncta separata. Cand gasesti o celula cu valoare >= X iei fiecare din cei 4 vecini ai ei. Daca vecinul are si el valoare >= X vei uni multimea disjuncta a celulei cu cea a vecinului. X este bun ca raspuns daca (x1, y1) si (x2, y2) se afla in aceeasi multime disjuncta.
Acum folosim cautarea binara a lui Patrascu. Sa zicem ca am incercat deja puterile {19, 18, ..., i + 1} iar acum incercam puterea 2 ^ i. Daca raspunsurile pana acum au fost {X1, X2, ..., XQ} acum raspunsurile vor fi {X1 + 2 ^ i, X2 + 2 ^ i, ..., XQ + 2 ^ i}. Trebuie sa determinam pentru fiecare din valorile astea noi daca e un raspuns bun. Daca e, vom adauga 2 ^ i la ea. Daca nu, nu vom adauga.
Am redus problema la a raspunde la Q intrebari de forma: (x0, y0, x1, y1, val): exista un drum intre (x0, y0) si (x1, y1) cu toate numerele >= val? Putem rezolva online fiecare query, dar nu castigam nimic fata de solutia brute. Ideea e sa gasim un algoritm offline, adica sa raspundem la intrebari intr-o ordine avantajoasa.
Sortam toate cele Q intrebari dupa valoarea val, in ordine descrescatoare. Acum, sa zicem ca am raspuns la primele i query-uri. Folosim metoda de mai sus, cu multimi disjuncte. In multimea disjuncta vor fi unite toate nr cu valori >= val_i . Pentru query-ul i + 1 stiu ca val_(i + 1) <= val_i . De asemenea, stiu ca toate numerele >= val_i sunt deja in multimea disjuncta. Deci, mai trebuie unite doar numerele cuprinse intre val_(i + 1) si val_i. Daca am sorta si valorile initiale ale matricei descrescator, ne putem plimba cu un pointer pe sirul valorilor si sa adaugam fiecare valoare o singura data in multimea disjuncta. Fiecare valoare e adaugata o singura data, deci se fac N ^ 2 modificari pe multimea disjuncta pt fiecare 2 ^ i. Deci obtii O((N ^ 2 * log* N + Q) * logN).
|