제출 #1343322

#제출 시각아이디문제언어결과실행 시간메모리
1343322avighnaIOI 바이러스 (JOI21_fever)C++20
57 / 100
2243 ms114456 KiB
#include <bits/stdc++.h>

using namespace std;

struct point {
  int64_t x, y;
};

enum dir { RIGHT, LEFT, UP, DOWN };
enum linetype { NORMAL, X_PLUS_Y, X_MINUS_Y, X_EQUALS_CONST, Y_EQUALS_CONST };

int64_t get(linetype type, int64_t x, int64_t y) {
  return array<int64_t, 5>({0, x + y, x - y, x, y})[type];
};

enum onwhat { ON_X, ON_Y };

struct maptype {
  linetype linetyp;
  onwhat onwha;
  dir direction;
  auto operator<=>(const maptype &) const = default;
};

struct fraction {
  int64_t n, d;
  void normalize() {
    if (d < 0) {
      n = -n, d = -d;
    }
    int64_t g = gcd(n >= 0 ? n : -n, d);
    n /= g, d /= g;
  }
  fraction(int64_t n = 0) : n(n), d(1) {}
  fraction(int64_t n, int64_t d) : n(n), d(d) { normalize(); }
  auto operator<=>(const fraction &o) const { return n * o.d <=> o.n * d; }
  fraction operator+(const fraction &o) const { return fraction(n * o.d + o.n * d, d * o.d); }
  fraction operator-(const fraction &o) const { return fraction(n * o.d - o.n * d, d * o.d); }
  fraction operator*(const fraction &o) const { return fraction(n * o.n, d * o.d); }
  fraction operator/(const fraction &o) const { return fraction(n * o.d, d * o.n); }
  template <typename T>
  friend fraction operator+(T x, const fraction &f) { return fraction(x) + f; }
  template <typename T>
  friend fraction operator-(T x, const fraction &f) { return fraction(x) - f; }
  template <typename T>
  friend fraction operator*(T x, const fraction &f) { return fraction(x) * f; }
};

template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;

static const array<array<dir, 3>, 4> choose = {{{{LEFT, DOWN, DOWN}}, {{LEFT, UP, UP}}, {{RIGHT, RIGHT, DOWN}}, {{RIGHT, RIGHT, UP}}}};
array<onwhat, 4> diron = {ON_Y, ON_Y, ON_X, ON_X};
array<linetype, 4> ltype = {Y_EQUALS_CONST, Y_EQUALS_CONST, X_EQUALS_CONST, X_EQUALS_CONST};
static const array<array<dir, 3>, 4> dirlock = {{{{RIGHT, RIGHT, RIGHT}}, {{LEFT, LEFT, LEFT}}, {{RIGHT, LEFT, RIGHT}}, {{LEFT, RIGHT, LEFT}}}};
static const array<array<dir, 3>, 4> dirwant = {{{{DOWN, UP, LEFT}}, {{UP, DOWN, RIGHT}}, {{LEFT, RIGHT, DOWN}}, {{RIGHT, LEFT, UP}}}};
static const array<array<int, 3>, 4> use_ub = {{{{0, 1, 0}}, {{1, 0, 1}}, {{0, 1, 0}}, {{1, 0, 1}}}};

int solve(int n, vector<point> a) {
  vector<dir> dirs = {RIGHT};
  for (int i = 1; i < n; ++i) {
    auto [x, y] = a[i];
    dirs.push_back(choose[(x < 0) * 2 + (y < 0)][(abs(y) < abs(x) ? 0 : abs(y) == abs(x) ? 1 : 2)]);
  }
  map<maptype, map<int, set<pair<fraction, int>>>> mps;
  for (int i = 0; i < n; ++i) {
    auto [x, y] = a[i];
    mps[{X_MINUS_Y, ON_X, dirs[i]}][x - y].insert({x, i});
    mps[{X_MINUS_Y, ON_Y, dirs[i]}][x - y].insert({y, i});
    mps[{X_PLUS_Y, ON_X, dirs[i]}][x + y].insert({x, i});
    mps[{X_PLUS_Y, ON_Y, dirs[i]}][x + y].insert({y, i});
    mps[{X_EQUALS_CONST, ON_Y, dirs[i]}][x].insert({y, i});
    mps[{Y_EQUALS_CONST, ON_X, dirs[i]}][y].insert({x, i});
  }

  min_heap<pair<fraction, pair<int64_t, pair<linetype, dir>>>> pq;
  pq.push({0, {0, {NORMAL, LEFT}}});
  vector vis(n, vector<int>(9));
  auto flat = [](pair<linetype, dir> p) -> int { return p.first + 4 * (p.first != NORMAL && p.second != LEFT); };
  while (!pq.empty()) {
    auto [t, p] = pq.top();
    auto [i, m] = p;
    pq.pop();
    if (vis[i][flat(m)]) {
      continue;
    }
    vis[i][flat(m)] = 1;
    auto [x, y] = a[i];
    if (m.first != NORMAL) {
      pq.push({t, {i, {NORMAL, LEFT}}});
      int c = m.first == X_EQUALS_CONST;
      auto *st = &mps[{m.first, c ? ON_Y : ON_X, dirs[i]}][get(m.first, x, y)];
      int64_t qty = c ? y : x;
      auto it = st->find({qty, i});
      int s = m.first == X_EQUALS_CONST || m.first == Y_EQUALS_CONST;
      if (m.second == RIGHT && it != --st->end()) {
        pq.push({t + (next(it)->first - qty) / (s + 1), {next(it)->second, m}});
      }
      if (m.second == LEFT && it != st->begin()) {
        pq.push({t + (qty - prev(it)->first) / (s + 1), {prev(it)->second, m}});
      }
      continue;
    }
    auto add = [&](fraction dist, int64_t y, linetype z, dir direc) { pq.push({dist, {y, {z, direc}}}); };
    auto lb = [&](set<pair<fraction, int>> &st, int64_t val, int mul, linetype linetyp, dir direc) {
      if (auto it = st.lower_bound({val + mul * t, -1}); it != st.end()) {
        add((it->first - val) / mul, it->second, linetyp, direc);
      }
    };
    auto ub = [&](set<pair<fraction, int>> &st, int64_t val, int mul, linetype linetyp, dir direc) {
      if (auto it = st.upper_bound({val - mul * t, n}); it != st.begin()) {
        it--;
        add((val - it->first) / mul, it->second, linetyp, direc);
      }
    };
    int64_t qty = int(dirs[i]) < 2 ? y : x;
    array<function<void(set<pair<fraction, int>> &, int64_t, int, linetype, dir)>, 2> f = {lb, ub};
    f[use_ub[dirs[i]][0]](mps[{X_MINUS_Y, diron[dirs[i]], dirwant[dirs[i]][0]}][x - y], qty, 1, X_MINUS_Y, dirlock[dirs[i]][0]);
    f[use_ub[dirs[i]][1]](mps[{X_PLUS_Y, diron[dirs[i]], dirwant[dirs[i]][1]}][x + y], qty, 1, X_PLUS_Y, dirlock[dirs[i]][1]);
    f[use_ub[dirs[i]][2]](mps[{ltype[dirs[i]], onwhat(1 - int(diron[dirs[i]])), dirwant[dirs[i]][0]}][get(ltype[dirs[i]], x, y)], x + y - qty, 2, ltype[dirs[i]], dirlock[dirs[i]][2]);
  }
  int ans = 0;
  for (int i = 0; i < n; ++i) {
    ans += vis[i][NORMAL];
  }
  return ans;
}

int32_t main() {
  cin.tie(nullptr)->sync_with_stdio(false);

  int n;
  cin >> n;
  vector<point> a(n);
  for (auto &[x, y] : a) {
    cin >> x >> y;
  }
  for (auto &[x, y] : a | views::drop(1)) {
    x -= a[0].x, y -= a[0].y;
  }
  a[0] = {0, 0};

  auto rotate = [&]() {
    for (auto &[x, y] : a) {
      int64_t nx = y, ny = -x;
      x = nx, y = ny;
    }
  };

  int ans = solve(n, a);
  rotate();
  ans = max(ans, solve(n, a));
  rotate();
  ans = max(ans, solve(n, a));
  rotate();
  cout << max(ans, solve(n, a)) << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...