제출 #1306237

#제출 시각아이디문제언어결과실행 시간메모리
1306237cpismylifeOwORoads (CEOI20_roads)C++20
15 / 100
35 ms30188 KiB
#include <bits/stdc++.h>

using namespace std;

const long long mod = 1e9 + 7;
const int MaxN = 1e6 + 5;
const int MaxLog = 20;

long long Rand(long long l, long long r)
{
    assert(l <= r);
    long long res = 0;
    for (int x = 0; x < 4; x++)
    {
        res = (res << 15) ^ (rand() & ((1ll << 15) - 1));
    }
    return l + res % (r - l + 1);
}

struct Line
{
    long long x1, y1, x2, y2;
    bool isin;
};

int n;
Line arr[MaxN];

void Inp()
{
    cin >> n;
    for (int x = 1; x <= n; x++)
    {
        cin >> arr[x].x1 >> arr[x].y1 >> arr[x].x2 >> arr[x].y2;
        if (arr[x].x1 > arr[x].x2 || (arr[x].x1 == arr[x].x2 && arr[x].y1 > arr[x].y2))
        {
            swap(arr[x].x1, arr[x].x2);
            swap(arr[x].y1, arr[x].y2);
        }
        arr[x].isin = false;
    }
}

struct Vector
{
    long long x, y;

    Vector() = default;

    Vector(long long _x, long long _y)
    {
        x = _x;
        y = _y;
    }

    long long operator * (const Vector& other) const
    {
        return this->x * other.y - this->y * other.x;
    }
};

bool cmp(int a, int b)
{
    assert(arr[a].x1 <= arr[b].x1 && arr[b].x1 <= arr[a].x2);
    if (arr[a].x1 == arr[a].x2)
    {
        return arr[a].x2 < arr[b].x1;
    }
    Vector ca(arr[a].x2 - arr[a].x1, arr[a].y2 - arr[a].y1);
    Vector cb(arr[b].x1 - arr[a].x1, arr[b].y1 - arr[a].y1);
    return (ca * cb > 0);
}

struct Cell;

struct Column
{
    vector<Cell> cells;
    int val;
    long long vx, vy;
};

Column* curpos[MaxN];

struct Cell
{
    Column* prev;
    Column* nxt;

    Cell() = default;

    Cell(Column* _prev, Column* _nxt)
    {
        prev = _prev;
        nxt = _nxt;
    }
};

struct SkipList
{
    Column *head, *tail;

    SkipList()
    {
        head = new Column;
        tail = new Column;
        head->val = tail->val = 0;
        head->vx = head->vy = tail->vx = tail->vy = -1;
        for (int x = 0; x < MaxLog; x++)
        {
            head->cells.push_back(Cell(nullptr, tail));
            tail->cells.push_back(Cell(head, nullptr));
        }
    }

    bool empty()
    {
        return head->cells[0].nxt == tail;
    }

    Column* lower_bound(int v)
    {
        Column* res = head;
        for (int x = MaxLog - 1; x >= 0; x--)
        {
            while (res->cells[x].nxt != tail && cmp(res->cells[x].nxt->val, v))
            {
                res = res->cells[x].nxt;
            }
        }
        return res;
    }

    void Insert(int v)
    {
        if (arr[v].isin)
        {
            return;
        }
        arr[v].isin = true;
        Column* add = new Column;
        add->val = v;
        add->vx = arr[v].x1;
        add->vy = arr[v].y1;
        add->cells.push_back(Cell(nullptr, nullptr));
        while ((int)add->cells.size() < MaxLog && (Rand(1, 1e9) & 1))
        {
            add->cells.push_back(Cell(nullptr, nullptr));
        }
        Column* pos = head;
        for (int x = MaxLog - 1; x >= 0; x--)
        {
            while (pos->cells[x].nxt != tail && cmp(pos->cells[x].nxt->val, v))
            {
                pos = pos->cells[x].nxt;
            }
            Column* con = pos->cells[x].nxt;
            if (x < (int)add->cells.size())
            {
                add->cells[x].prev = pos;
                add->cells[x].nxt = con;
                pos->cells[x].nxt = add;
                con->cells[x].prev = add;
            }
        }
        curpos[v] = add;
    }

    void Delete(int v)
    {
        if (!arr[v].isin)
        {
            return;
        }
        arr[v].isin = false;
        Column* pos = curpos[v];
        pos->cells[0].prev->vx = arr[v].x2;
        pos->cells[0].prev->vy = arr[v].y2;
        for (int x = 0; x < (int)pos->cells.size(); x++)
        {
            Column* prev = pos->cells[x].prev;
            Column* nxt = pos->cells[x].nxt;
            prev->cells[x].nxt = nxt;
            nxt->cells[x].prev = prev;
        }
        curpos[v] = nullptr;
        delete pos;
    }
};

vector<pair<long long, int>> compress;
SkipList ds;

void Exc()
{
    for (int x = 1; x <= n; x++)
    {
        compress.push_back(make_pair(arr[x].x1, x));
        compress.push_back(make_pair(arr[x].x2, x + n));
    }
    sort(compress.begin(), compress.end());
    int pre = 0;
    for (int x = 0; x < (int)compress.size(); x++)
    {
        int y = x;
        while (y < (int)compress.size() && compress[x].first == compress[y].first)
        {
            y++;
        }
        y--;
        for (int z = x; z <= y; z++)
        {
            if (compress[z].second <= n)
            {
                int u = compress[z].second;
                if (pre > 0 || !ds.empty())
                {
                    if (ds.empty())
                    {
                        cout << arr[pre].x2 << " " << arr[pre].y2 << " " << arr[u].x1 << " " << arr[u].y1 << "\n";
                    }
                    else
                    {
                        Column* res = ds.lower_bound(u);
                        if (res == ds.head && !(~ds.head->vx))
                        {
                            res = res->cells[0].nxt;
                            cout << arr[res->val].x1 << " " << arr[res->val].y1 << " " << arr[u].x1 << " " << arr[u].y1 << "\n";
                        }
                        else
                        {
                            cout << res->vx << " " << res->vy << " " << arr[u].x1 << " " << arr[u].y1 << "\n";
                        }
                    }
                }
                ds.Insert(u);
            }
            else
            {
                int u = compress[z].second - n;
                pre = u;
                ds.Delete(u);
            }
        }
        x = y;
    }
}

int main()
{
    //freopen("ROADS.INP", "r", stdin);
    //freopen("ROADS.OUT", "w", stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    srand(time(nullptr));
    int test = 1;
    //cin >> test;
    for (int x = 1; x <= test; x++)
    {
        Inp();
        Exc();
    }
    return 0;
}
#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...