답안 #987698

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
987698 2024-05-23T11:33:40 Z Double_Slash Walk (CEOI06_walk) C++17
100 / 100
411 ms 77704 KB
#include <bits/stdc++.h>
#define debug(x) [&] { auto _x = x; cerr << __LINE__ << ": " << #x << " = " << _x << endl; }()
 
using namespace std;
using ll = long long;
using pint = pair<int, int>;
#define all(x) x.begin(), x.end()
 
const int MAX = 1e6;
const ll INF = 1e18;
 
struct Val {
    ll dist = INF;
    int x, y;
 
    bool operator<(const Val &o) const { return dist < o.dist; }
};
 
struct Node {
    int l, r;
    Val val;
    bool lazy = false;
    Node *lc, *rc;
 
    Node(int l, int r, const vector<int> &arr) : l(l), r(r) {
        if (l < r) {
            int m = l + ((r - l) >> 1);
            lc = new Node{l, m, arr};
            rc = new Node{m + 1, r, arr};
        }
        this->l = arr[l], this->r = arr[r];
    }
 
    void clean() {
        if (lazy) {
            val.dist = INF;
            if (l < r) lc->lazy = rc->lazy = lazy;
            lazy = false;
        }
    }
 
    Val query(int ql, int qr) {
        if (ql > r or qr < l) return {};
        clean();
        if (l >= ql and r <= qr) return val;
        return min(lc->query(ql, qr), rc->query(ql, qr));
    }
 
    void update(int i, const Val &v) {
        clean();
        if (i < l or i > r) return;
        if (l == r) {
            val = v;
            return;
        }
        lc->update(i, v);
        rc->update(i, v);
        val = min(lc->val, rc->val);
    }
 
    void clear(int ul, int ur) {
        clean();
        if (ul > r or ur < l) return;
        if (l >= ul and r <= ur) {
            lazy = true;
            clean();
            return;
        }
        lc->clear(ul, ur);
        rc->clear(ul, ur);
        val = min(lc->val, rc->val);
    }
};
int X, Y, n;
vector<pint> s[MAX + 1], e[MAX + 1];
map<pint, pint> pre;
 
int main() {
    cin >> X >> Y >> n;
    vector<int> arr{{0}};
    for (int i = 0; i < n; ++i) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if (x1 > x2) swap(x1, x2);
        if (y1 > y2) swap(y1, y2);
        s[x1].emplace_back(y1, y2);
        e[x2].emplace_back(y1, y2);
        arr.emplace_back(y1 - 1), arr.emplace_back(y2 + 1);
    }
    sort(all(arr));
    arr.erase(unique(all(arr)), arr.end());
    Node *up = new Node{0, (int) arr.size() - 1, arr}, *down = new Node{0, (int) arr.size() - 1, arr};
    up->update(0, {0, 0, 0}), down->update(0, {0, 0, 0});
    map<int, int> blocks;
    blocks[-MAX - 2] = -MAX - 2;
    blocks[MAX + 2] = MAX + 2;
    auto dp = [&] (int y) {
        auto it = blocks.upper_bound(y);
        auto a = up->query(prev(it)->second + 1, y), b = down->query(y, it->first - 1);
        a.dist += y, b.dist -= y;
        return min(a, b);
    };
    for (int x = 0; x <= X; ++x) {
        vector<pint> points;
        for (auto [l, r]: s[x]) points.emplace_back(l - 1, 0), points.emplace_back(r + 1, 0);
        sort(all(points));
        points.erase(unique(all(points)), points.end());
        for (auto &[y, v]: points) {
            auto a = dp(y);
            pre[{x - 1, y}] = {a.x, a.y};
            v = a.dist;
        }
        for (auto [y, v]: points) {
            up->update(y, {v - y, x - 1, y});
            down->update(y, {v + y, x - 1, y});
        }
        for (auto [l, r]: e[x - 1]) blocks.erase(l);
        for (auto [l, r]: s[x]) {
            up->clear(l, r);
            down->clear(l, r);
            blocks[l] = r;
        }
    }
    auto a = dp(Y);
    cout << a.dist + X << endl;
    pre[{X, Y}] = {a.x, a.y};
    vector<pint> coords{{X, Y}};
    while (X or Y) {
        tie(X, Y) = pre[{X, Y}];
        coords.emplace_back(X, Y);
    }
    vector<pint> ans;
    while (coords.size() >= 2) {
        if (coords.end()[-2].first != coords.back().first) {
            if (ans.empty() or ans.back().second) ans.emplace_back(coords.end()[-2].first - coords.back().first, 0);
            else ans.back().first += coords.end()[-2].first - coords.back().first;
        }
        if (coords.end()[-2].second != coords.back().second) {
            if (ans.empty() or ans.back().first) ans.emplace_back(0, coords.end()[-2].second - coords.back().second);
            else ans.back().second += coords.end()[-2].second - coords.back().second;
        }
        coords.pop_back();
    }
    cout << ans.size() << endl;
    for (auto [x, y]: ans) cout << x << " " << y << endl;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 23 ms 47196 KB Output is correct
2 Correct 24 ms 47196 KB Output is correct
3 Correct 28 ms 47356 KB Output is correct
4 Correct 39 ms 47960 KB Output is correct
5 Correct 411 ms 77704 KB Output is correct
6 Correct 166 ms 62832 KB Output is correct
7 Correct 243 ms 59568 KB Output is correct
8 Correct 366 ms 66844 KB Output is correct
9 Correct 343 ms 65732 KB Output is correct
10 Correct 383 ms 66164 KB Output is correct