Problem p02680 (C++) — buggy submission, verdict: Runtime Error

//------------------------------------------------------------
#define MOD 1000000007

//------------------------------------------------------------
#if 1
#include <bits/stdc++.h>
using namespace std;

//------------------------------------------------------------
using ll = long long;
#define int ll

#define FOR(i, s, e) for (ll i = ll(s); i < (ll)e; ++i)
#define RFOR(i, s, e) for (ll i = ll(e) - 1; i >= ll(s); --i)
#define REP(i, n) for (ll i = 0, i##_size = n; i < i##_size; ++i)
#define RREP(i, n) for (ll i = ll(n) - 1; i >= 0; --i)

//------------------------------------------------------------
template <class T> struct arr : public vector<T> {
  arr() {}
  arr(ll n, T v = T()) : vector<T>(n, v) {}
  void init(ll n, T v = T()) {
    this->clear();
    this->resize(n, v);
  }
  ll sz() const { return (ll)this->size(); }
  void pb(T v) { this->push_back(v); }
  void sort() { std::sort(this->begin(), this->end()); }
  void rsort() { std::sort(this->begin(), this->end(), greater<T>()); }
  void uniqueErase() {
    this->erase(std::unique(this->begin(), this->end()), this->end());
  }
};
using ints = arr<ll>;
using intss = arr<arr<ll>>;

template <class T> struct que : public queue<T> {
  ll sz() const { return (ll)this->size(); }
  T popfront() {
    T v = this->front();
    this->pop();
    return v;
  }
};

template <class A, class B> struct pr {
  union {
    A a;
    A key;
    A first;
    A x;
  };
  union {
    B b;
    B value;
    B second;
    B y;
  };

  pr() : a(A()), b(B()){};
  pr(A a_, B b_) : a(a_), b(b_) {}
  pr(pr const &r) : a(r.a), b(r.b){};
  pr(pair<A, B> const &r) : a(r.first), b(r.second){};

  bool operator==(pr const &r) const { return a == r.a && b == r.b; }
  bool operator!=(pr const &r) const { return !((*this) == r); }
  bool operator<(pr const &r) const {
    if (a == r.a) {
      return b < r.b;
    }
    return a < r.a;
  }

  pr operator+(pr v) const { return pr(x, y) += v; }
  pr operator-(pr v) const { return pr(x, y) -= v; }

  pr &operator+=(pr v) {
    x += v.x;
    y += v.y;
    return *this;
  }
  pr &operator-=(pr v) {
    x -= v.x;
    y -= v.y;
    return *this;
  }

  friend istream &operator>>(istream &is, pr &p) {
    is >> p.a >> p.b;
    return is;
  }
};
using pint = pr<ll, ll>;
using pints = arr<pint>;

template <class K, class V> struct mp : public map<K, V> {
  bool get(K const &k, V *v) {
    auto it = this->find(k);
    if (it != this->end()) {
      *v = it->second;
      return true;
    }
    return false;
  }
};

template <class T> struct arr2 {
  vector<vector<T>> vec;

  arr2() {}
  arr2(int w, int h, T const &value = T()) {
    vec.resize(h, vector<T>(w, value));
  }
  arr2(arr2 const &r) { vec = r.vec; }
  arr2(arr2 &&r) { vec = move(r.vec); }
  arr2 &operator=(arr2 const &r) {
    vec = r.vec;
    return *this;
  }
  arr2 &operator=(arr2 &&r) {
    vec = move(r.vec);
    return *this;
  }

  int width() const { return (int)vec[0].size(); }
  int height() const { return (int)vec.size(); }

  void init(int w, int h, T const &value = T()) {
    vec.clear();
    vec.resize(h, vector<T>(w, value));
  }
  T &operator()(int x, int y) { return vec.at(y).at(x); }
  T const &operator()(int x, int y) const { return vec.at(y).at(x); }

  T &operator()(pint p) { return vec.at(p.y).at(p.x); }
  T const &operator()(pint p) const { return vec.at(p.y).at(p.x); }
};

//------------------------------------------------------------
#if defined(TEST)
extern istream &myInputStream;
extern ostream &myOutputStream;
#else
istream &myInputStream = cin;
ostream &myOutputStream = cout;
#endif

struct input {
  template <class A, class B> void exec(pair<A, B> &var) {
    myInputStream >> var.first >> var.second;
  }

  template <class T> void exec(T &var) { myInputStream >> var; }

  template <class T> operator T() {
    T var;
    exec(var);
    return var;
  }
} input;

struct inputs {
  ll n;
  inputs(ll n_) : n(n_) {}

  template <class T> operator arr<T>() {
    arr<T> var(n);
    REP(i, n) { var[i] = (T)input; };
    return var;
  }
};

template <class T> void output(T var) { myOutputStream << (var) << '\\n'; }

//------------------------------------------------------------
template <class T> void chmin(T &a, T b) {
  if (b < a) {
    a = b;
  }
}
template <class T> void chmax(T &a, T b) {
  if (b > a) {
    a = b;
  }
}

constexpr int gcd(int a, int b) {
  if (a < 0) {
    a = -a;
  }
  if (b < 0) {
    b = -b;
  }
  if (a == 0) {
    return b;
  }
  if (b == 0) {
    return a;
  }

  while (int c = a % b) {
    a = b;
    b = c;
  }
  return b;
}

//------------------------------------------------------------
struct bfs {
  ints froms;
  ints steps;

  bfs(int N, intss const &adjacency) {
    froms.init(N, -1);
    steps.init(N, -1);

    que<ll> queue;
    queue.push(0);
    froms[0] = 0;
    steps[0] = 0;

    while (queue.empty() == false) {
      ll p = queue.popfront();

      for (ll n : adjacency[p]) {
        if (froms[n] != -1) {
          continue;
        }

        froms[n] = p;
        steps[n] = steps[p] + 1;
        queue.push(n);
      }
    }
  }
};

//------------------------------------------------------------
template <int M> struct modint {
  int raw;

  modint() { raw = 0; }
  modint(int v) {
    if (v < 0) {
      raw = (v % M) + M;
    } else if (v >= M) {
      raw = v % M;
    } else {
      raw = v;
    }
  }
  modint operator+(modint v) const { return modint(raw) += v; }
  modint operator-(modint v) const { return modint(raw) -= v; }
  modint operator*(modint v) const { return modint(raw) *= v; }

  modint &operator+=(modint v) {
    raw += v.raw;
    if (raw >= M) {
      raw -= M;
    }
    return *this;
  }
  modint &operator-=(modint v) {
    raw -= v.raw;
    if (raw < 0) {
      raw += M;
    }
    return *this;
  }
  modint &operator*=(modint v) {
    raw = (raw * v.raw) % M;
    return *this;
  }
  modint pow(int n) const { return modint::pow(raw, n); }
  static modint pow(int a, int n) {
    if (n < 0) {
      // not support
      abort();
    }

    int r = 1;
    while (n) {
      if (n & 1) {
        r = (r * a) % M;
      }
      a = (a * a) % M;
      n >>= 1;
    }
    return modint(r);
  }

  friend istream &operator>>(istream &is, modint &m) {
    int v;
    is >> v;
    m = modint(v);
    return is;
  }
  friend ostream &operator<<(ostream &os, modint const &m) {
    return os << m.raw;
  }
};

using mint = modint<MOD>;
using mints = arr<mint>;

//------------------------------------------------------------
#if defined(TEST)
#include "test.hpp"
#else
void myMain();
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(16);
  myMain();
  return 0;
}
#endif
#endif

struct HorizontalLine {
  int y;
  int left;
  int right;
};

struct VerticalLine {
  int x;
  int top;
  int bottom;
};

//------------------------------------------------------------
void myMain() {
  int N = input;
  int M = input;

  arr<int> xs;
  arr<int> ys;
  arr<VerticalLine> vls(N);
  arr<HorizontalLine> hls(M);
  REP(i, N) {
    auto &vl = vls[i];
    vl.top = input;
    vl.bottom = input;
    vl.x = input;

    ys.pb(vl.top);
    ys.pb(vl.bottom);
    xs.pb(vl.x);
  }

  REP(i, M) {
    auto &hl = hls[i];
    hl.y = input;
    hl.left = input;
    hl.right = input;

    ys.pb(hl.y);
    xs.pb(hl.left);
    xs.pb(hl.right);
  }

  // 問題と座標系が縦横逆になってる

  // xs/ysは圧縮座標から実座標への変換テーブルになる
  xs.pb(0);
  ys.pb(0);
  xs.sort();
  xs.uniqueErase();
  ys.sort();
  ys.uniqueErase();

  // 実座標から圧縮座標への変換テーブル
  map<int, int> r2ix;
  map<int, int> r2iy;
  REP(i, xs.sz()) { r2ix[xs[i]] = i; }
  REP(i, ys.sz()) { r2iy[ys[i]] = i; }

  // bomber座標系に
  arr2<char> field(xs.sz() * 2 - 1, ys.sz() * 2 - 1, 0);
  REP(i, N) {
    if (i >= vls.size()) {
      continue;
    }
    auto const &vl = vls[i];

    if (r2ix.find(vl.x) == r2ix.end()) {
      continue;
    }

    int bx = r2ix[vl.x] * 2;
    if (bx >= field.width()) {
      continue;
    }

    if (r2iy.find(vl.top) == r2iy.end()) {
      continue;
    }
    if (r2iy.find(vl.bottom) == r2iy.end()) {
      continue;
    }
    if (r2iy[vl.top] * 2 >= field.height()) {
      continue;
    }
    if (r2iy[vl.bottom] * 2 >= field.height()) {
      continue;
    }

    for (int by = r2iy[vl.top] * 2; by <= r2iy[vl.bottom] * 2; ++by) {
      field(bx, by) = 1;
    }
  }
  REP(i, M) {
    if (i >= hls.size()) {
      continue;
    }
    auto const &hl = hls[i];

    if (r2iy.find(hl.y) == r2iy.end()) {
      continue;
    }

    int by = r2iy[hl.y] * 2;
    if (by >= field.height()) {
      continue;
    }

    if (r2ix.find(hl.left) == r2ix.end()) {
      continue;
    }
    if (r2ix.find(hl.right) == r2ix.end()) {
      continue;
    }
    if (r2ix[hl.left] * 2 >= field.width()) {
      continue;
    }
    if (r2ix[hl.right] * 2 >= field.width()) {
      continue;
    }

    for (int bx = r2ix[hl.left] * 2; bx <= r2ix[hl.right] * 2; ++bx) {
      field(bx, by) = 1;
    }
  }

  // REP(y, field.height()) {
  //	REP(x, field.width()) {
  //		if (field(x, y)) {
  //			cout << "#";
  //		}
  //		else {
  //			cout << " ";
  //		}
  //	}
  //	cout << endl;
  // }

  bool over = false;

  // bomber座標指定で面積取得
  auto GetSize = [&xs, &ys, &over](int bx, int by) -> int {
    if (bx % 2 == 0 || by % 2 == 0) {
      return 0;
    }
    if (bx % 2 == 0 || by % 2 == 0) {
      return 0;
    }

    int ix = bx / 2;
    int iy = by / 2;

    if (ix + 1 >= xs.sz()) {
      over = true;
      return 0;
    }
    if (iy + 1 >= ys.sz()) {
      over = true;
      return 0;
    }

    int w = xs[ix + 1] - xs[ix];
    int h = ys[iy + 1] - ys[iy];
    return w * h;
  };

  int cx = r2ix[0] * 2 + 1;
  int cy = r2iy[0] * 2 + 1;

  que<pint> queue;
  queue.push(pint(cx, cy));
  if (cx < field.width() && cy < field.height()) {
    field(cx, cy) = 1;
  }
  int ans = GetSize(cx, cy);

  while (queue.empty() == false) {
    pint p = queue.popfront();

    for (pint around : {pint(-1, 0), pint(0, -1), pint(1, 0), pint(0, 1)}) {
      pint next = p + around;

      if (next.x < 0 || next.x >= field.width() || next.y < 0 ||
          next.y >= field.height()) {
        over = true;
        break;
      }

      if (field(next) != 0) {
        continue;
      }

      field(next) = 1;
      queue.push(next);
      ans += GetSize(next.x, next.y);
    }
  }

  if (over) {
    output("INF");
  } else {
    output(ans);
  }
}


Error: 0

Fixed submission:

//------------------------------------------------------------
#define MOD 1000000007

//------------------------------------------------------------
#if 1
#include <bits/stdc++.h>
using namespace std;

//------------------------------------------------------------
using ll = long long;
#define int ll

#define FOR(i, s, e) for (ll i = ll(s); i < (ll)e; ++i)
#define RFOR(i, s, e) for (ll i = ll(e) - 1; i >= ll(s); --i)
#define REP(i, n) for (ll i = 0, i##_size = n; i < i##_size; ++i)
#define RREP(i, n) for (ll i = ll(n) - 1; i >= 0; --i)

//------------------------------------------------------------
template <class T> struct arr : public vector<T> {
  arr() {}
  arr(ll n, T v = T()) : vector<T>(n, v) {}
  void init(ll n, T v = T()) {
    this->clear();
    this->resize(n, v);
  }
  ll sz() const { return (ll)this->size(); }
  void pb(T v) { this->push_back(v); }
  void sort() { std::sort(this->begin(), this->end()); }
  void rsort() { std::sort(this->begin(), this->end(), greater<T>()); }
  void uniqueErase() {
    this->erase(std::unique(this->begin(), this->end()), this->end());
  }
};
using ints = arr<ll>;
using intss = arr<arr<ll>>;

template <class T> struct que : public queue<T> {
  ll sz() const { return (ll)this->size(); }
  T popfront() {
    T v = this->front();
    this->pop();
    return v;
  }
};

template <class A, class B> struct pr {
  union {
    A a;
    A key;
    A first;
    A x;
  };
  union {
    B b;
    B value;
    B second;
    B y;
  };

  pr() : a(A()), b(B()){};
  pr(A a_, B b_) : a(a_), b(b_) {}
  pr(pr const &r) : a(r.a), b(r.b){};
  pr(pair<A, B> const &r) : a(r.first), b(r.second){};

  bool operator==(pr const &r) const { return a == r.a && b == r.b; }
  bool operator!=(pr const &r) const { return !((*this) == r); }
  bool operator<(pr const &r) const {
    if (a == r.a) {
      return b < r.b;
    }
    return a < r.a;
  }

  pr operator+(pr v) const { return pr(x, y) += v; }
  pr operator-(pr v) const { return pr(x, y) -= v; }

  pr &operator+=(pr v) {
    x += v.x;
    y += v.y;
    return *this;
  }
  pr &operator-=(pr v) {
    x -= v.x;
    y -= v.y;
    return *this;
  }

  friend istream &operator>>(istream &is, pr &p) {
    is >> p.a >> p.b;
    return is;
  }
};
using pint = pr<ll, ll>;
using pints = arr<pint>;

template <class K, class V> struct mp : public map<K, V> {
  bool get(K const &k, V *v) {
    auto it = this->find(k);
    if (it != this->end()) {
      *v = it->second;
      return true;
    }
    return false;
  }
};

template <class T> struct arr2 {
  vector<vector<T>> vec;

  arr2() {}
  arr2(int w, int h, T const &value = T()) {
    vec.resize(h, vector<T>(w, value));
  }
  arr2(arr2 const &r) { vec = r.vec; }
  arr2(arr2 &&r) { vec = move(r.vec); }
  arr2 &operator=(arr2 const &r) {
    vec = r.vec;
    return *this;
  }
  arr2 &operator=(arr2 &&r) {
    vec = move(r.vec);
    return *this;
  }

  int width() const { return (int)vec[0].size(); }
  int height() const { return (int)vec.size(); }

  void init(int w, int h, T const &value = T()) {
    vec.clear();
    vec.resize(h, vector<T>(w, value));
  }
  T &operator()(int x, int y) { return vec.at(y).at(x); }
  T const &operator()(int x, int y) const { return vec.at(y).at(x); }

  T &operator()(pint p) { return vec.at(p.y).at(p.x); }
  T const &operator()(pint p) const { return vec.at(p.y).at(p.x); }
};

//------------------------------------------------------------
#if defined(TEST)
extern istream &myInputStream;
extern ostream &myOutputStream;
#else
istream &myInputStream = cin;
ostream &myOutputStream = cout;
#endif

struct input {
  template <class A, class B> void exec(pair<A, B> &var) {
    myInputStream >> var.first >> var.second;
  }

  template <class T> void exec(T &var) { myInputStream >> var; }

  template <class T> operator T() {
    T var;
    exec(var);
    return var;
  }
} input;

struct inputs {
  ll n;
  inputs(ll n_) : n(n_) {}

  template <class T> operator arr<T>() {
    arr<T> var(n);
    REP(i, n) { var[i] = (T)input; };
    return var;
  }
};

template <class T> void output(T var) { myOutputStream << (var) << '\\n'; }

//------------------------------------------------------------
template <class T> void chmin(T &a, T b) {
  if (b < a) {
    a = b;
  }
}
template <class T> void chmax(T &a, T b) {
  if (b > a) {
    a = b;
  }
}

constexpr int gcd(int a, int b) {
  if (a < 0) {
    a = -a;
  }
  if (b < 0) {
    b = -b;
  }
  if (a == 0) {
    return b;
  }
  if (b == 0) {
    return a;
  }

  while (int c = a % b) {
    a = b;
    b = c;
  }
  return b;
}

//------------------------------------------------------------
struct bfs {
  ints froms;
  ints steps;

  bfs(int N, intss const &adjacency) {
    froms.init(N, -1);
    steps.init(N, -1);

    que<ll> queue;
    queue.push(0);
    froms[0] = 0;
    steps[0] = 0;

    while (queue.empty() == false) {
      ll p = queue.popfront();

      for (ll n : adjacency[p]) {
        if (froms[n] != -1) {
          continue;
        }

        froms[n] = p;
        steps[n] = steps[p] + 1;
        queue.push(n);
      }
    }
  }
};

//------------------------------------------------------------
template <int M> struct modint {
  int raw;

  modint() { raw = 0; }
  modint(int v) {
    if (v < 0) {
      raw = (v % M) + M;
    } else if (v >= M) {
      raw = v % M;
    } else {
      raw = v;
    }
  }
  modint operator+(modint v) const { return modint(raw) += v; }
  modint operator-(modint v) const { return modint(raw) -= v; }
  modint operator*(modint v) const { return modint(raw) *= v; }

  modint &operator+=(modint v) {
    raw += v.raw;
    if (raw >= M) {
      raw -= M;
    }
    return *this;
  }
  modint &operator-=(modint v) {
    raw -= v.raw;
    if (raw < 0) {
      raw += M;
    }
    return *this;
  }
  modint &operator*=(modint v) {
    raw = (raw * v.raw) % M;
    return *this;
  }
  modint pow(int n) const { return modint::pow(raw, n); }
  static modint pow(int a, int n) {
    if (n < 0) {
      // not support
      abort();
    }

    int r = 1;
    while (n) {
      if (n & 1) {
        r = (r * a) % M;
      }
      a = (a * a) % M;
      n >>= 1;
    }
    return modint(r);
  }

  friend istream &operator>>(istream &is, modint &m) {
    int v;
    is >> v;
    m = modint(v);
    return is;
  }
  friend ostream &operator<<(ostream &os, modint const &m) {
    return os << m.raw;
  }
};

using mint = modint<MOD>;
using mints = arr<mint>;

//------------------------------------------------------------
#if defined(TEST)
#include "test.hpp"
#else
void myMain();
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(16);
  myMain();
  return 0;
}
#endif
#endif

struct HorizontalLine {
  int y;
  int left;
  int right;
};

struct VerticalLine {
  int x;
  int top;
  int bottom;
};

//------------------------------------------------------------
void myMain() {
  int N = input;
  int M = input;

  arr<int> xs;
  arr<int> ys;
  arr<VerticalLine> vls(N);
  arr<HorizontalLine> hls(M);
  REP(i, N) {
    auto &vl = vls[i];
    vl.top = input;
    vl.bottom = input;
    vl.x = input;

    ys.pb(vl.top);
    ys.pb(vl.bottom);
    xs.pb(vl.x);
  }

  REP(i, M) {
    auto &hl = hls[i];
    hl.y = input;
    hl.left = input;
    hl.right = input;

    ys.pb(hl.y);
    xs.pb(hl.left);
    xs.pb(hl.right);
  }

  // 問題と座標系が縦横逆になってる

  // xs/ysは圧縮座標から実座標への変換テーブルになる
  xs.pb(0);
  ys.pb(0);
  xs.sort();
  xs.uniqueErase();
  ys.sort();
  ys.uniqueErase();

  // 実座標から圧縮座標への変換テーブル
  map<int, int> r2ix;
  map<int, int> r2iy;
  REP(i, xs.sz()) { r2ix[xs[i]] = i; }
  REP(i, ys.sz()) { r2iy[ys[i]] = i; }

  // bomber座標系に
  arr2<char> field(xs.sz() * 2 - 1, ys.sz() * 2 - 1, 0);
  REP(i, N) {
    if (i >= vls.size()) {
      continue;
    }
    auto const &vl = vls[i];

    if (r2ix.find(vl.x) == r2ix.end()) {
      continue;
    }

    int bx = r2ix[vl.x] * 2;
    if (bx >= field.width()) {
      continue;
    }

    if (r2iy.find(vl.top) == r2iy.end()) {
      continue;
    }
    if (r2iy.find(vl.bottom) == r2iy.end()) {
      continue;
    }
    if (r2iy[vl.top] * 2 >= field.height()) {
      continue;
    }
    if (r2iy[vl.bottom] * 2 >= field.height()) {
      continue;
    }

    for (int by = r2iy[vl.top] * 2; by <= r2iy[vl.bottom] * 2; ++by) {
      field(bx, by) = 1;
    }
  }
  REP(i, M) {
    if (i >= hls.size()) {
      continue;
    }
    auto const &hl = hls[i];

    if (r2iy.find(hl.y) == r2iy.end()) {
      continue;
    }

    int by = r2iy[hl.y] * 2;
    if (by >= field.height()) {
      continue;
    }

    if (r2ix.find(hl.left) == r2ix.end()) {
      continue;
    }
    if (r2ix.find(hl.right) == r2ix.end()) {
      continue;
    }
    if (r2ix[hl.left] * 2 >= field.width()) {
      continue;
    }
    if (r2ix[hl.right] * 2 >= field.width()) {
      continue;
    }

    for (int bx = r2ix[hl.left] * 2; bx <= r2ix[hl.right] * 2; ++bx) {
      field(bx, by) = 1;
    }
  }

  // REP(y, field.height()) {
  //	REP(x, field.width()) {
  //		if (field(x, y)) {
  //			cout << "#";
  //		}
  //		else {
  //			cout << " ";
  //		}
  //	}
  //	cout << endl;
  // }
  bool over = false;

  // bomber座標指定で面積取得
  auto GetSize = [&xs, &ys, &over](int bx, int by) -> int {
    if (bx % 2 == 0 || by % 2 == 0) {
      return 0;
    }
    if (bx % 2 == 0 || by % 2 == 0) {
      return 0;
    }

    int ix = bx / 2;
    int iy = by / 2;

    if (ix + 1 >= xs.sz()) {
      over = true;
      return 0;
    }
    if (iy + 1 >= ys.sz()) {
      over = true;
      return 0;
    }

    int w = xs[ix + 1] - xs[ix];
    int h = ys[iy + 1] - ys[iy];
    return w * h;
  };

  int cx = r2ix[0] * 2 + 1;
  int cy = r2iy[0] * 2 + 1;

  que<pint> queue;

  queue.push(pint(cx, cy));
  field(cx, cy) = 1;
  int ans = GetSize(cx, cy);

  while (queue.empty() == false) {
    pint p = queue.popfront();

    for (pint around : {pint(-1, 0), pint(0, -1), pint(1, 0), pint(0, 1)}) {
      pint next = p + around;

      if (next.x < 0 || next.x >= field.width() || next.y < 0 ||
          next.y >= field.height()) {
        over = true;
        break;
      }

      if (field(next) != 0) {
        continue;
      }

      field(next) = 1;
      queue.push(next);
      ans += GetSize(next.x, next.y);
    }
  }

  if (over) {
    output("INF");
  } else {
    output(ans);
  }
}