Editorial for Gric


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.

Submitting an official solution before solving the problem yourself is a bannable offence.

Na osnovu ograničenja y_i \geq H možemo zaključiti da će, ukoliko posmatramo proizvoljnu vertikalnu pravu koja prolazi kroz keks, u svakom trenutku, presek preostalog keksa sa tom pravom biti ili prazan, ili će biti jedna duž. Kad ovo ograničenje ne bi postojalo, bilo bi moguće da Pavle pojede parče iz "sredine" keksa, u tom slučaju bi taj presek mogao da se sastoji iz više duži. Osnovna ideja koja je zajednička svim rešenjima jeste da se održava niz b, gde je b_i preostalo parče keksa na poziciji x = i. U početku, pre svih upita imamo b_i = 0 za svako i \in [0, W]. Treba obratiti pažnju pri implementaciji da se ne štampa negativan broj, odnosno, ako neki krug prelazi iks-osu, ne treba smanjivati b_i ispod 0.

U prvom podzadatku, radijus kruga je 1, pa su izmene na nizu b trivijalne - ukoliko krug ima y=H, stavljamo b_{x} = H-1.

U drugom podzadatku, postavljamo b_x = \min(b_x, y-2) i  b_{x-1} = \min(b_{x-1}, y - \sqrt{3}), slično za b_{x+1}, naravno, ukoliko su ove x-koordinate u segmentu [0, W]. Vremenska složenost rešenja prva dva podzadatka je O(Q + W).

Treći podzadatak je uopštenje prethodne ideje. Tačna vrednost na koju treba postaviti broj b_i je \min(b_i, y - \sqrt{(R+i-x)(R-i+x)}) za sve i \in [0, W] \cap [x-R, x+R]. Ova formula se može izvesti geometrijski, pomoću Pitagorine teoreme. Vremenska složenost je O(W + QR).

Za rešavanje četvrtog i petog podzadatka neophodne su nam sledeće opservacije. Prva je ta da je dovoljno posmatrati oblik koji formiraju donji polukružni lukovi dodatih krugova. Druga, ključna je da se nijedna dva takva luka ne mogu seći više od jednom, osim ako se ne poklapaju. Ovo se može dokazati na sledeći način: Posmatrajmo neka dva kruga. Ukoliko se oni ne poklapaju, oni se mogu seći na najviše dva mesta. Na osnovu toga što imaju isti radijus, tačke preseka su centralno simetrično raspoređene u odnosu na tačku koja se nalazi na sredini duži koja spaja centre ta dva kruga. Kako ovaj centar ima y-koordinatu veću nego "niži" od ta dva kruga, i jedna od presečnih tačaka sigurno isto ima veću y-koordinatu od centra nižeg druga, pa ne učestvuje u preseku donjih polukružnica.

Četvrti podzadatak se može rešiti tako što se eksplicitno izračuna oblik keksa. Sortiramo sve krugove po x-koordinati i obrađujemo ih u ovom redosledu. Pomoću steka održavamo skup polukružnica koje učestvuju u konačnom obliku keksa, kao i pozicije preseka susednih polukružnica. Odgovor na neki upit možemo naći binarnom pretragom po dobijenom nizu polukružnica, ili jednostavnije, obradom celog niza polukružnica tj. eksplicitnim nalaženjem svih vrednosti b_i, u jednom prolazu kroz niz. Ovo rešenje je primenljivo upravo zato što se svake dve polukružnice seku najviše jednom. Ovu ideju nije moguće primeniti ukoliko to ne bi važilo, na primer, ako bi se radijusi datih kružnica razlikovali. Vremenska složenost je O(W + Q \log Q).

Odavde je jasno da rešenje četvrtog podzadatka podseća na ono što se zove "trik sa konveksnim omotačem", gde se nalazi oblik koji formira presek poluravni. Drugi način da se izračuna ovaj presek poluravni jeste pomoću takozvanog LiChao segmentnog stabla, pa je prirodno pokušati prilagoditi tu strukturu podataka za ovaj problem.

Naime, formirajmo segmentno stablo, gde se u svakom čvoru nalazi opis jedne polukružnice, koja cela pokriva pridruženi segment u stablu, odnosno, takva da ako je čvor odgovoran za segment [x_l, x_r], tada za kružnicu važi x-R \leq x_l \leq x_r \leq x+R (uslov 1), gde je (x,y) njen centar. Dodatno, namećemo ograničenje da za list, tj. čvor koji odgovara segmentu [x, x], put u stablu od tog lista do korena sadrži krug koji u x dostiže najmanju y-koordinatu, u svakom trenutku. Ako ovo važi, jasno je da na upit možemo odgovoriti u O(\log W), samo posmatranjem tih O(\log W) čvorova na putu od lista do korena.

Kako dodati novi krug? Posmatrajmo rekurzivnu funkciju koja polazi od korena stabla, koji odgovara čvoru koji čuva segment [0, W]. Ukoliko za trenutni čvor ne važi uslov 1, i segmenti koji odgovaraju krugu i čvoru se ne seku, možemo odmah izaći, inače rekurzivno dodajemo krug u oba čvora deteta trenutnog čvora. Na dalje pretpostavimo da uslov 1 važi. Ako u trenutnom čvoru nema nikakvog kruga, slobodno možemo staviti u taj čvor novi krug i izaći iz funkcije. Još jedan slučaj gde možemo odmah staviti krug i izaći jeste ako je novi polukrug ceo ispod starog na celom segmentu trenutnog čvora [x_l, x_r], što se može jednostavno proveriti ako izračunamo y-koordinate preseka polukrugova sa [x_l, x_r], kao po formuli datoj u rešenju podzadatka 3. Ukoliko je novi polukrug ceo iznad starog na tom segmentu, ne moramo da ga dodajemo, već odmah izlazimo iz funkcije. Inače, ova dva polukruga se seku na tačno jednom mestu, unutar segmenta. U taj čvor možemo upisati onaj od ta dva kruga koji je "dominantan" na bar jednoj polovini segmenta, dok drugi možemo rekurzivno ubaciti u drugo dete trenutnog čvora. Vremenska složenost ovog postupka se razlikuje od onog za obično segmentno stablo. U toku rekurzije dolazimo do O(\log W) čvorova za koje važi uslov 1, a za svaki od njih imamo po jedan rekurzivni put koji se može sastojati iz najviše O(\log W) čvorova, pa je vremenska složenost dodavanja jednog kruga O(\log^2W), a celog rešenja O(W + Q \log^2 W).


Comments

There are no comments at the moment.