제출 #1334218

#제출 시각아이디문제언어결과실행 시간메모리
1334218LIAWalk (CEOI06_walk)C++17
80 / 100
129 ms47820 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define v vector
#define lp(i, s, e) for (int i = s; i < e; ++i)
#define tpl tuple<ll, ll, ll, ll, ll, ll>

const int MAX_Y = 600005;
int seg[4 * MAX_Y];
int lazy_seg[4 * MAX_Y];

void push(int node, int l, int r) {
  if (lazy_seg[node] != -1) {
    seg[node] = lazy_seg[node];
    if (l != r) {
      lazy_seg[2 * node] = lazy_seg[node];
      lazy_seg[2 * node + 1] = lazy_seg[node];
    }
    lazy_seg[node] = -1;
  }
}

void update(int node, int l, int r, int ql, int qr, int val) {
  push(node, l, r);
  if (l > qr || r < ql)
    return;
  if (l >= ql && r <= qr) {
    lazy_seg[node] = val;
    push(node, l, r);
    return;
  }
  int mid = (l + r) / 2;
  update(2 * node, l, mid, ql, qr, val);
  update(2 * node + 1, mid + 1, r, ql, qr, val);
}

int query(int node, int l, int r, int pos) {
  push(node, l, r);
  if (l == r)
    return seg[node];
  int mid = (l + r) / 2;
  if (pos <= mid)
    return query(2 * node, l, mid, pos);
  return query(2 * node + 1, mid + 1, r, pos);
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);

  memset(lazy_seg, -1, sizeof(lazy_seg));
  memset(seg, -1, sizeof(seg));

  ll dest_x, dest_y;
  cin >> dest_x >> dest_y;
  ll n;
  cin >> n;
  vector<tpl> vec;
  v<ll> y_val;

  y_val.push_back(dest_y);
  y_val.push_back(0);

  v<ll> B_left(n + 2), B_right(n + 2), B_bottom(n + 2), B_top(n + 2);

  lp(i, 0, n) {
    ll a, b, c, d;
    cin >> a >> b >> c >> d;
    if (a >= dest_x)
      continue;
    c = min(c, dest_x);

    B_left[i + 1] = a;
    B_right[i + 1] = c;
    B_bottom[i + 1] = b;
    B_top[i + 1] = d;

    y_val.push_back(b);
    y_val.push_back(d);
    y_val.push_back(b - 1);
    y_val.push_back(d + 1);

    vec.push_back({a, b, c, d, 0, i + 1});
    vec.push_back({c, d, a, b, 1, i + 1});
  }

  sort(y_val.begin(), y_val.end());
  y_val.erase(unique(y_val.begin(), y_val.end()), y_val.end());
  int sz = y_val.size();

  auto get_y = [&](ll y) {
    return lower_bound(y_val.begin(), y_val.end(), y) - y_val.begin();
  };

  vec.push_back({0, 0, 0, 0, 1, 0});
  sort(vec.begin(), vec.end());

  update(1, 0, sz - 1, 0, sz - 1, n + 1);

  v<v<ll>> dp(n + 2, v<ll>(2, 0));
  v<v<int>> next_hit(n + 2, v<int>(2, 0));

  auto get_dist = [&](ll y, int hit, ll &cost) {
    if (hit == n + 1) {
      cost = abs(y - dest_y);
      return;
    }
    ll cost_b = abs(y - (B_bottom[hit] - 1)) + dp[hit][0];
    ll cost_t = abs(y - (B_top[hit] + 1)) + dp[hit][1];
    cost = min(cost_b, cost_t);
  };

  ll ans = 1e18;
  int start_hit = -1;

  for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
    auto [cx, cy, ox, oy, type, idx] = *it;

    if (type == 1) {
      if (idx == 0) {
        start_hit = query(1, 0, sz - 1, get_y(0));
        ll cost;
        get_dist(0, start_hit, cost);
        ans = dest_x + cost;
      } else {
        int h1 = query(1, 0, sz - 1, get_y(oy - 1));
        next_hit[idx][0] = h1;
        get_dist(oy - 1, h1, dp[idx][0]);

        int h2 = query(1, 0, sz - 1, get_y(cy + 1));
        next_hit[idx][1] = h2;
        get_dist(cy + 1, h2, dp[idx][1]);
      }
    } else {
      update(1, 0, sz - 1, get_y(cy), get_y(oy), idx);
    }
  }

  cout << ans << "\n";

  ll curr_X = 0, curr_Y = 0;
  int curr_hit = start_hit;
  vector<pair<ll, ll>> moves;

  auto add_move = [&](ll dx, ll dy) {
    if (dx == 0 && dy == 0)
      return;
    if (!moves.empty()) {
      auto &last = moves.back();
      if ((last.first == 0 && dx == 0) || (last.second == 0 && dy == 0)) {
        last.first += dx;
        last.second += dy;
        if (last.first == 0 && last.second == 0)
          moves.pop_back();
        return;
      }
    }
    moves.push_back({dx, dy});
  };

  while (curr_hit != n + 1) {
    ll nx = B_left[curr_hit];
    add_move(nx - curr_X, 0);
    curr_X = nx;

    ll cost_b = abs(curr_Y - (B_bottom[curr_hit] - 1)) + dp[curr_hit][0];
    ll cost_t = abs(curr_Y - (B_top[curr_hit] + 1)) + dp[curr_hit][1];

    if (cost_b < cost_t) {
      ll ny = B_bottom[curr_hit] - 1;
      add_move(0, ny - curr_Y);
      curr_Y = ny;

      ll rx = B_right[curr_hit];
      add_move(rx - curr_X, 0);
      curr_X = rx;

      curr_hit = next_hit[curr_hit][0];
    } else {
      ll ny = B_top[curr_hit] + 1;
      add_move(0, ny - curr_Y);
      curr_Y = ny;

      ll rx = B_right[curr_hit];
      add_move(rx - curr_X, 0);
      curr_X = rx;

      curr_hit = next_hit[curr_hit][1];
    }
  }

  add_move(dest_x - curr_X, 0);
  add_move(0, dest_y - curr_Y);

  vector<pair<ll, ll>> final_moves;
  for (auto m : moves) {
    if (m.first != 0 || m.second != 0) {
      final_moves.push_back(m);
    }
  }

  cout << final_moves.size() << "\n";
  for (auto [dx, dy] : final_moves) {
    cout << dx << " " << dy << "\n";
  }
}
#Verdict Execution timeMemoryGrader output
Fetching results...