제출 #1306616

#제출 시각아이디문제언어결과실행 시간메모리
1306616chrisvilchesWalk (CEOI06_walk)C++20
0 / 100
273 ms28560 KiB
#include <bits/stdc++.h>
using namespace std;

struct Point {
  int x, y;
  bool operator<(const Point p) const { return x < p.x || (x == p.x && y < p.y); }
  int dist(const Point p) const { return abs(p.x - x) + abs(p.y - y); }

  bool operator==(const Point p) const { return x == p.x && y == p.y; }
};

ostream& operator<<(ostream& os, const Point p) {
  return os << "(" << p.x << ", " << p.y << ")";
}

int main() {
  int n;
  Point dest;
  while (cin >> dest.x >> dest.y >> n) {
    // cerr << endl << "---------------------------------------------" << endl << endl;
    vector<tuple<int, int, int, int>> events;

    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);

      // TODO: Maybe I can use each y independently on each event (no need to have both in
      // one item). I think I need to remove in the range, so I can't do that!!!
      events.emplace_back(x1 - 1, 1, y1 - 1, y2 + 1);
      events.emplace_back(x2 + 1, 0, y1 - 1, y2 + 1);
    }

    // TODO: what should the type be in this event????
    events.emplace_back(dest.x, 1, dest.x, dest.y);

    sort(events.begin(), events.end());

    map<int, Point> m;

    map<Point, Point> prev_point;

    const int inf = 1e7;

    m[0] = {0, 0};
    // TODO: Maybe this will overflow in some cases.
    // TODO: This data is weird lmao
    m[INT_MIN] = {0, -inf};
    m[INT_MAX] = {0, inf};

    const auto update = [&](const int x, const int y) {
      const auto it0 = m.lower_bound(y);
      assert(it0 != m.end());
      assert(it0 != m.begin());
      const auto it1 = it0->first == y ? it0 : prev(it0);

      const Point p{x, y};
      if (prev_point.count(p)) return;

      if (p.dist(it0->second) < p.dist(it1->second)) {
        // use it0
        prev_point[p] = it0->second;
        m[p.y] = p;
      } else {
        // use it1
        prev_point[p] = it1->second;
        m[p.y] = p;
      }
      // cerr << prev_point[p] << " ----> " << p << endl;
    };

    for (const auto& [x, type, y1, y2] : events) {
      // cerr << format("x: {}, type: {}, y = [{}, {}]", x, type, y1, y2) << endl;

      // TODO: I'm not using the `type` lol
      update(x, y1);
      update(x, y2);

      // TODO: I think I have to remove the items between y1 and y2???????
      while (true) {
        const auto it = m.lower_bound(y1 + 1);
        // TODO: This line fixed it?? but verify what I did (the -1 specifically)
        if (y2 - 1 <= it->first) break;
        m.erase(it);
      }

      // cerr << "curr map content:" << endl;
      // for (const auto& [y, p] : m) {
      //   cerr << "    " << y << " : " << p << endl;
      // }
    }

    vector<Point> path;

    Point curr = dest;

    while (!(curr.x == 0 && curr.y == 0)) {
      path.emplace_back(curr);
      if (!prev_point.count(curr)) {
        // cerr << "not found! prev of : " << curr << endl;
        break;
      }
      // assert(prev_point.count(curr));
      if (curr == prev_point[curr]) {
        // cerr << "equal!!! " << curr << endl;
        break;
      }
      curr = prev_point[curr];
    }

    path.emplace_back(0, 0);

    int total_len = 0;
    for (size_t i = 0; i < path.size() - 1; i++) {
      total_len += path[i].dist(path[i + 1]);
    }

    cout << total_len << endl;

    // cerr << "path:" << endl;
    // cerr << "total length: " << total_len << endl;
    // for (const Point p : path) {
    //   cerr << p << endl;
    // }
  }
}
#Verdict Execution timeMemoryGrader output
Fetching results...