Submission #1185399

#TimeUsernameProblemLanguageResultExecution timeMemory
1185399UnforgettableplRoads (CEOI20_roads)C++20
30 / 100
86 ms11224 KiB
#include <bits/stdc++.h>
using namespace std;

#define int long long
#define ld long double

int c = 0;

struct line{
    int x1,x2,y1,y2,id;
    line(int x1,int y1,int x2,int y2):x1(x1),y1(y1),x2(x2),y2(y2),id(++c){}
    long double operator()(int x) const{
        if(x==x2)return (ld)y2;
        if(x1==x2)return (ld)y1; // edge case
        return (ld)(y2-y1)*(ld)(x-x1)/(ld)(x2-x1) + (ld)y1;
    }
    bool operator<(const line& other) const{
        int pt = max(x1,other.x1);
        return this->operator()(pt) < other(pt);
    }
    bool operator<(const pair<int,int>& other) const{
        return this->operator()(other.first) < other.second;
    }
};

int32_t main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    cin >> N;
    vector<tuple<int,int,int,int>> lines(N);
    map<int,vector<int>> removals;
    for(auto&[x1,y1,x2,y2]:lines){
        cin >> x1 >> y1 >> x2 >> y2;
        if(make_pair(x1,y1) > make_pair(x2,y2)){
            swap(x1,x2);
            swap(y1,y2);
        }
    }
    sort(lines.begin(),lines.end());
    map<pair<int,int>,pair<int,int>> opt; // [lidx,ridx] -> (y,x)
    set<line> limits;
    vector<line> answer;
    limits.emplace(-1e8,-1e8,1e8,-1e8);
    limits.emplace(-1e8,1e8,1e8,1e8);
    opt[{1,2}] = {-1e8,-1e8};
    auto findLimits = [&](int x,int y){
        int upper = limits.upper_bound(line(x,y,x,y))->id;
        int lower = (--limits.upper_bound(line(x,y,x,y)))->id;
        return make_pair(lower,upper);
    };
    for(auto&[x1,y1,x2,y2]:lines){
        // process removals
        while(removals.begin()!=removals.end() and removals.begin()->first<x1){
            for(int&i:removals.begin()->second){
                limits.erase(limits.lower_bound(line(removals.begin()->first,i,removals.begin()->first,i))); // figure out how to delete
                opt[findLimits(removals.begin()->first,i)]=max(opt[findLimits(removals.begin()->first,i)],{removals.begin()->first,i});
            }
            removals.erase(removals.begin());
        }
        // process actually
        auto lim = findLimits(x1,y1);
        answer.emplace_back(x1,y1,opt[{lim.first,lim.second}].first,opt[{lim.first,lim.second}].second);
        // add this to removals if not vertical
        auto t = findLimits(x1,y1);
        if(x1!=x2){
            removals[x2].emplace_back(y2);
            // add this to limitations
            limits.emplace(x1,y1,x2,y2);
            opt[{t.first,c}]={x1,y1};
            opt[{c,t.second}]={x1,y1};
        } else {
            opt[t]={x1,y2};
        }
    }
    for(line&x:answer){
        if(x.x2<-1e7)continue;
        cout << x.x1 << ' ' << x.y1 << ' ' << x.x2 << ' ' << x.y2 << '\n';
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...