Zadanie

Interpol naháňa nebezpečného zločinca: doktora Horibilného. Pomocou interpolácie (ako ináč) práve zistili jeho približnú polohu – niekedy dnes sa zjaví niekde na dlhej rovnej ceste vedúcej cez soľné polia v Utahu. Rýchlo tam preto presmerovali kamery všetkých špionážnych satelitov.

Každý z týchto satelitov má slepé miesto. Toto má konštantnú veľkosť a ako sa satelit hýbe, aj toto miesto sa hýbe po ceste – budeme predpokladať, že rovnomernou konštantnou rýchlosťou.

Je možné, že napriek množstvu satelitov nedokáže Interpol zločinca nájsť?

Úloha

Na osi \(x\) (predstavujúcej cestu) sa nachádza \(n\) uzavretých intervalov. Každý interval predstavuje slepé miesto jedného zo satelitov. V tejto chvíli platí, že \(i\)-ty z týchto intervalov pokrýva súradnice \([\ell_i,r_i]\). Interval \(i\) sa hýbe doprava rýchlosťou \(v_i\). Teda po uplynutí času \(t\) bude slepý interval satelitu \(i\) začínať na súradnici \(\ell_i + t\cdot v_i\).

Zistite, či niekedy bude existovať nejaká časť cesty, ktorú v danom okamihu nebude nahrávať žiadny satelit. Ak áno, vypočítajte, aký najdlhší úsek cesty bude mať túto vlastnosť.

Formát vstupu

V prvom riadku vstupu je číslo \(n\) (\(1\leq n\leq 100\,000\)): počet satelitov. V každom z ďalších \(n\) riadkov je jedna trojica celých čísel \(\ell_i\), \(r_i\), \(v_i\) (\(0\leq \ell_i < r_i \leq 10^6\), \(1\leq v_i\leq 10^6\)).

Formát výstupu

Vypíšte jeden riadok a v ňom jedno celé číslo – najdlhšiu dĺžku intervalu, ktorý v nejakom okamihu nebol v zábere žiadneho zo satelitov.

(Toto číslo môže byť reálne, viď posledný príklad. Vypíšte ho s presnosťou na aspoň 7 desatinných miest. Výstupy, ktoré budú mať od nášho dostatočne malú odchýlku, budú akceptované.)

Ak hľadaný interval (ani degenerovaný) neexistuje, vypíšte namiesto toho číslo \(-1\).

Hodnotenie

Vaše riešenia budeme testovať na štyroch sadách vstupov. V jednotlivých sadách platí \(n\leq 5\), \(n\leq 20\), \(n\leq 1\,000\) a \(n\leq 100\,000\). V druhej a tretej sade navyše platí, že žiaden vstup nemá výstup \(-1\) ani \(0\).

Príklady

Input:

2
5 7 1
10 13 1

Output:

-1

Slepé miesta satelitov sa v tejto chvíli neprekrývajú, takže každý bod cesty vidí aspoň jeden z nich. No a keďže sa obe slepé miesta hýbu tou istou rýchlosťou, toto ostane pravdou aj naďalej.

Input:

2
3 7 1
7 18 10

Output:

0

V tomto okamihu ani jeden zo satelitov nezaberá bod na súradnici 7, máme teda interval dĺžky 0, ktorý je nepozorovaný. V budúcnosti už nič lepšie (pre doktora Horibilného) nenastane.

Input:

3
40 140 30
130 180 10
47 190 1

Output:

44.4827586207

V čase \(t\approx 1.724\) budú slepé intervaly našich troch satelitov približne \([91.724,191.724]\), \([147.241,197.241]\) a \([48.724,191.724]\), čiže v danom okamihu interval \([147.241,191.724]\) nebude zaberaný ani jedným zo satelitov.

Zamyslime sa najskôr nad statickou verziou tejto úlohy: ak máme daných \(n\) úsekov cesty \([ x_i,y_i]\), ako vyzerá ich prienik? Kedy je neprázdny?

Aby nejaký bod \(x\) patril do prieniku všetkých intervalov, museli už všetky začať, teda musí platiť \(x\geq\max_i x_i\). Tiež musí platiť, že žiaden interval ešte nesmel skončiť, teda \(x\leq\min_j y_j\).

Z toho vidíme, že môžu nastať dva prípady: ak \(\max_i x_i > \min_j y_j\), prienik je prázdny – niektorý interval skončí skôr ako niektorý iný začne. V opačnom prípade je prienik neprázdny a je ním zjavne práve uzavretý interval \([\max_i x_i, \min_j y_j]\).

Dĺžka intervalu ako funkcia

Ak si v našej úlohe zvolíme nejaký konkrétny okamih \(t\geq 0\), vieme si vypočítať, ako v danom okamihu vyzerajú slepé intervaly: \(i\)-ty z nich bude \([\ell_i + tv_i, r_i + tv_i]\).

Nás zaujíma, akú najdlhšiu dĺžku (a pre aké \(t\)) bude mať tento interval. Uvažujme preto nasledujúcu funkciu: \(f(t) = \min_j (r_j + tv_j) - \max_i (\ell_i + tv_i)\). Zjavne platí, že ak \(f(t) < 0\), tak je v čase \(t\) prienik prázdny, a inak \(f(t)\) udáva jeho dĺžku. Našu úlohu teda vieme preformulovať tak, že hľadáme, pre ktoré \(t\geq 0\) nadobúda funkcia \(f\) svoje maximum.

Príklad funkcie f

Na prvom grafe nižšie vidíme, ako sa tri rôzne slepé intervaly pohybujú v čase. Na \(x\)-ovej osi je čas, na \(y\)-ovej vzdialenosť na ceste. Znázornené intervaly zodpovedajú poslednému príkladu v zadaní, až na to, že \(\ell_2\) je o čosi väčšie, aby to lepšie vyzeralo.

Čiarkované čiary predstavujú začiatky jednotlivých intervalov. Nás vždy zaujíma posledný začiatok (hodnota \(\max_i (\ell_i + tv_i)\)), čiže najvyššie sa nachádzajúca čiarkovaná čiara.

Analogicky nás v každom čase zaujíma prvý koniec intervalu, čiže najnižšie sa nachádzajúca plná čiara. Ak sa tá nachádza nad všetkými čiarkovanými, intervaly majú v danom čase neprázdny prienik.

Na druhom grafe sme vyfarbili oblasť, ktorá zodpovedá neprázdnemu prieniku intervalov, a hrubou čiarou sme vyznačili optimálne riešenie našej úlohy.

Dôležitá vlastnosť funkcie f

V čase \(t=0\) vidíme, že najvyššia čiarkovaná čiara zodpovedá intervalu 1, zatiaľ čo najnižšia plná čiara intervalu 0. No a keďže interval 0 sa hýbe rýchlosťou 30 a interval 1 len rýchlosťou 10, keď teraz pôjdeme v čase ďalej, bude dĺžka prieniku plynule rásť (rýchlosťou \(30-10 = 20\) za jednotku času).

V čase \(t=50/29\) sa spodnou plnou čiarou stane čiara zodpovedajúca intervalu 2. Ten sa hýbe len rýchlosťou 1. Od tohto okamihu ďalej teda bude čiarkovaná čiara plnú. Dĺžka prieniku sa teda bude meniť o \(1-10 = -9\) za jednotku času.

V čase \(t=9/2\) nastane ďalšia zmena: hornou čiarkovanou čiarou sa stane čiara zodpovedajúca intervalu 0. Od tejto chvíle sa dĺžka prieniku mení rýchlosťou \(1-30 = -29\) za jednotku času, a čoskoro už prienik prestane existovať.

Na tomto príklade si môžeme všimnúť všeobecné pravidlo, ktoré bude vždy platiť: rýchlosť, ktorou rastie dĺžka prieniku, sa môže s rastúcim časom . Totiž vždy, keď nastane zmena najvrchnejšej čiarkovanej čiary, tá nová rastie rýchlejšie, a vždy, keď nastane zmena najspodnejšej plnej čiary, tá nová rastie od tej predchádzajúcej pomalšie.

Keďže na začiatku môže byť rýchlosť rastu kladná, znamená to, že samotná (presnejšie, hodnota funkcie \(f\), ktorá nás zaujíma) vo všeobecnosti .

My teraz potrebujeme nájsť maximum takejto funkcie. Spravíme to binárnym vyhľadávaním.

Binárne vyhľadávanie

V ľubovoľnom čase \(t\) si vieme v čase \(O(n)\) nájsť aj najspodnejšiu plnú čiaru, aj najvrchnejšiu čiarkovanú, a u oboch sa pozrieť na to, ako rýchlo rastú. Rozdiel týchto dvoch hodnôt nám povie, či v danom bode funkcia \(f\) ešte rastie, je práve konštantná, alebo už klesá.

Začneme tým, že sa pozrieme na čas \(t=0\). Ak už v tomto okamihu \(f\) nerastie, je \(f(0)\) odpoveďou, ktorú hľadáme a môžeme skončiť.

Označme teraz \(m\) najväčšie číslo na vstupe (či už ide o súradnicu alebo rýchlosť). Pripomíname, že pre testovacie dáta platilo \(m\leq 10^6\). Potom tvrdíme, že po čase \(m\) už nenastane žiadna zmena: od tohto času ďalej musí byť aj čiarkovaná aj plná čiara stále tá istá. Totiž ak iná bola od nej rýchlejšie/pomalšie rastúca, tak na začiatku mala táto pred ňou najviac \(m\), a keďže sú všetky čísla celé, tá druhá čiara tento náskok dobiehala aspoň rýchlosťou 1 za jednotku času.

(Algebraicky, priesečník priamok \(a+bt\) a \(c+dt\), kde \(c\not= d\), je v bode \(t=(a-c)/(d-b)\), no a v základnom tvare má tento zlomok má čitateľ \(\leq m\) a menovateľ \(\geq 1\).)

Máme teraz dve pozorovania: v čase \(t_{lo}=0\) funkcia \(f\) ešte rastie, zatiaľ čo v čase \(t_{hi}=m\) už určite nerastie. Od tohto okamihu ďalej môžeme použiť spomínané binárne vyhľadávanie: dokola opakujeme, že sa pozrieme do stredu intervalu, vyhodnotíme, či tam \(f\) ešte rastie alebo už nerastie, a podľa toho posunieme buď \(t_{lo}\) alebo \(t_{hi}\).

Trocha technických detailov na záver

Pri praktickej implementácii si treba dať pozor na zaokrúhľovacie chyby. Hodnotu optimálneho \(t\), a teda aj hodnotu \(f(t)\), zistíme len približne. Zadanie síce sľubuje, že testovač je tolerantný, ale aj tak ostáva jeden okrajový prípad, na ktorý si treba dať pozor: ak je optimálna odpoveď presne \(f(t)=0\), ale správne \(t\) netrafíme presne, dostaneme ako \(f(t)\) hodnotu, ktorá je tesne pod nulou. Ak vtedy prehlásime, že riešenie neexistuje, dáme nesprávnu odpoveď.

V jednom autorskom riešení sme pre istotu celý záver riešenia spravili exaktne: po dostatočnom počte iterácií binárneho vyhľadávania máme nájdené nejaké \(t\). Okrem tohto \(t\) si exaktne (ako zlomok dvoch veľkých čísel) dopočítame najbližšie menšie aj najbližšie väčšie \(t\), v ktorom sa mení niektorá hraničná čiara, a v oboch časoch exaktne vyhodnotíme funkciu \(f\). Takto máme istotu, že sme určite našli optimálne riešenie.

Na úspešné vyriešenie úlohy však stačilo aj použitie reálnych (floating-point) čísel a vhodné zaokrúhľovanie. Správny čas \(t\), aj správna odpoveď je totiž vždy zlomok, ktorého menovateľ je najviac \(m\). V našom prípade to teda znamená, že ak je maximum \(f\) naozaj záporné, tak je vždy menšie alebo rovné \(-10^{-6}\). A teda ak nám vychádza odpoveď výrazne bližšia nule, môžeme si byť rozumne istí, že správnou odpoveďou je samotná nula.

Diskusia

Tu môžte voľne diskutovať o riešení, deliť sa o svoje kusy kódu a podobne.

Pre pridávanie komentárov sa musíš prihlásiť.