#include #include #include #include #include using namespace std; // Největší společný dělitel dvou čísel long long gcd(long long a, long long b) { return (b==0) ? a : gcd(b, a%b); } // Zlomky a práce s nimi struct ratio { long long nom, den; // čitatel a jmenovatel ratio () { nom=0; den=1; } // jednička ratio(long long n) { nom=n; den=1; } // celé číslo -> zlomek ratio(long long n, long long d) { // úprava zlomku na základní tvar long long g = gcd(llabs(den), llabs(nom)); nom=n/g; den=d/g; if (den<0) { nom=-nom; den=-den; } } ratio& operator =(long long b) { nom=b; den=1; return *this; } ratio operator +(ratio b) const { return ratio(nom*b.den+b.nom*den, den*b.den); } ratio operator -(ratio b) const { return ratio(nom*b.den-b.nom*den, den*b.den); } ratio operator *(ratio b) const { return ratio(nom*b.nom, den*b.den); } ratio operator /(ratio b) const { return ratio(nom*b.den, den*b.nom); } bool operator <(ratio b) const { return (*this-b).nom < 0; } bool operator ==(ratio b) const { return nom==b.nom && den==b.den; } bool operator <=(ratio b) const { return (*this-b).nom <= 0; } float f() const { return (nom+0.0)/den; } // konverze na float }; ratio p(-900000); // zametací přímka // Úsečka ze vstupu struct usecka { ratio x1, y1, x2, y2; // souřadnice konců bool prunik(usecka pr) const { // má přímka průnik s jinou? ratio r = intersect(pr); return !(r e.type; } }; priority_queue U; // fronta událostí set S; // zadané úsečky typedef set ::iterator iter; // iterátor přes úsečky int n; // kolik je úseček usecka prk[1000000]; // pomocné pole na změněné přímky // Pokud se a s b proniká nad zametací přimkou, vytvoříme událost. void pronika(usecka a, usecka b) { event f; if (a.prunik(b)) { f.y = a.intersect(b); f.u = b; f.type = 1; if (p < f.y) U.push(f); } } void pridej(usecka u) { iter it = S.insert(u).first; // iterátor na přidaný prvek it--; pronika(*it, u); it++; it++; pronika(u, *it); } int main() { int x1, y1, x2, y2, i; FILE *f = fopen("lesnik.in", "r"), *fo=fopen("lesnik.out", "w"); fscanf(f, "%i", &n); for (i=0; i konec while (y == e.y && e.type == 0) { // nové přímky pridej(e.u); U.pop(); e=U.top(); // další událost } int k = 0; while (y == e.y && e.type == 1) { // průsečiky iter it = S.find(e.u), it2; if (it != S.end()) { // smažeme vše, co se mění ratio x = it->x(y); fprintf(fo, "%f %f\n", x.f(), y.f()); while (it->x(y) == x) it--; it++; while (it->x(y) == x) { it2 = it; it2++; prk[k++] = *it; // a zapamatujeme si, co se mění S.erase(it); it = it2; } } U.pop(); e = U.top(); } while (p == e.y && e.type == 2) { // vodorovné přímky usecka u; u.y1 = -1000000; u.y2 = 1000000; u.x1 = u.x2 = e.u.x1; iter i = S.lower_bound(u); for (iter i = S.lower_bound(u); i->x(y) <= e.u.x2; i++) fprintf(fo, "%f %f\n", i->x(y).f(), y.f()); U.pop(); e = U.top(); } p=y; // posuneme zametací přímku for (i=0; i