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

#include <algorithm> // other
#include <bitset>
#include <cassert> // c
#include <complex>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream> // io
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector> // container
using namespace std;

typedef int32_t i32;
typedef int64_t i64;
typedef i64 ll;
typedef uint32_t uint;
typedef uint64_t ull;

#define ALL(c) (begin(c)), (end(c))
#define REP(i, n) FOR(i, 0, n)
#define REPr(i, n) FORr(i, 0, n)
#define FOR(i, l, r) for (int i = (int)(l); i < (int)(r); ++i)
#define FORr(i, l, r) for (int i = (int)(r)-1; i >= (int)(l); --i)
#define EACH(it, o)                                                            \\
  for (__typeof((o).begin()) it = (o).begin(); it != (o).end(); ++it)
#define IN(l, v, r) ((l) <= (v) && (v) < (r))

// debug
#define DUMP(x) cerr << #x << " = " << (x)
#define DUMPLN(x) DUMP(x) << endl
#define DEBUG(x) DUMP(x) << LINE() << " " << __FILE__
#define DEBUGLN(x) DEBUG(x) << endl
#define LINE() cerr << " (L" << __LINE__ << ")"
#define LINELN() LINE() << endl
#define CHECK(exp, act)                                                        \\
  if (exp != act) {                                                            \\
    DUMPLN(exp);                                                               \\
    DEBUGLN(act);                                                              \\
  }
#define STOP(e)                                                                \\
  CHECK(e, true);                                                              \\
  if (!(e))                                                                    \\
    exit(1);

class range {
private:
  struct Iter {
    int v;
    int operator*() { return v; }
    bool operator!=(Iter &itr) { return v < itr.v; }
    void operator++() { ++v; }
  };
  Iter i, n;

public:
  range(int n) : i({0}), n({n}) {}
  range(int i, int n) : i({i}), n({n}) {}
  Iter &begin() { return i; }
  Iter &end() { return n; }
};

// output
template <typename T> ostream &operator<<(ostream &os, const vector<T> &as) {
  REP(i, as.size()) {
    if (i != 0)
      os << " ";
    os << as[i];
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<vector<T>> &as) {
  REP(i, as.size()) {
    if (i != 0)
      os << endl;
    os << as[i];
  }
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &ss) {
  EACH(a, ss) {
    if (a != ss.begin())
      os << " ";
    os << a;
  }
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename K, typename V>
ostream &operator<<(ostream &os, const map<K, V> &m) {
  bool isF = true;
  EACH(p, m) {
    if (!isF)
      os << endl;
    os << p;
    isF = false;
  }
  return os;
}

// input
char tmp[1000];
#define nextInt(n) scanf("%d", &n)
#define nextLong(n) scanf("%lld", &n) // I64d
#define nextDouble(n) scanf("%lf", &n)
#define nextChar(n) scanf("%c", &n)
#define nextString(n)                                                          \\
  scanf("%s", tmp);                                                            \\
  n = tmp

// values
template <class T> T INF() { assert(false); };
template <> int INF<int>() { return 1 << 28; };
template <> ll INF<ll>() { return 1LL << 58; };
template <> double INF<double>() { return 1e16; };

template <class T> T EPS() { assert(false); };
template <> int EPS<int>() { return 1; };
template <> ll EPS<ll>() { return 1LL; };
template <> double EPS<double>() { return 1e-8; };
template <> long double EPS<long double>() { return 1e-8; };

template <typename T> T pmod(T v, T M) { return (v % M + M) % M; }

namespace _double_tmpl {
typedef long double D;

static constexpr D Ae = 0;
D A(D a, D b) { return a + b; }
D Ainv(D a) { return -a; }
D S(D a, D b) { return A(a, Ainv(b)); }

static constexpr D Me = 1;
D M(D a, D b) { return a * b; }
D Minv(D a) { return 1.0 / a; };

int sig(D a, D b = 0) {
  return a < b - EPS<D>() ? -1 : a > b + EPS<D>() ? 1 : 0;
}
bool eq(D a, D b) { return sig(abs(a - b)) == 0; }

} // namespace _double_tmpl
using namespace _double_tmpl;
namespace Ps {
// using namespace _double_tmpl;
typedef complex<D> P, Vec;

#define X real()
#define Y imag()
istream &operator>>(istream &is, complex<D> &p) {
  D x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
bool eq(const P &a, const P &b) {
  return sig(a.real(), b.real()) == 0 && sig(a.imag(), b.imag()) == 0;
}
// a×b
D cross(const Vec &a, const Vec &b) { return imag(conj(a) * b); }
// a・b
D dot(const Vec &a, const Vec &b) { return real(conj(a) * b); }

int ccw(const P &a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS<D>())
    return +1; // counter clockwise
  if (cross(b, c) < -EPS<D>())
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;
}
} // namespace Ps
using namespace Ps;
namespace std {
bool operator<(const P &a, const P &b) {
  return make_pair(a.Y, a.X) < make_pair(b.Y, b.X);
  // return a.X != b.X ? a.X < b.X : a.Y < b.Y;
}
bool operator>(const P &a, const P &b) { return b < a; }
bool operator==(const P &a, const P &b) { return eq(a, b); }
}; // namespace std

namespace Polys {
typedef vector<P> Poly, ConvexPoly;

// O(nlogn)
ConvexPoly convex_hull(Poly ps) {
  int n = ps.size(), k = 0;
  sort(ALL(ps));
  Poly ch(2 * n);
  REP(i, n) { // lower-hull
    while (k > 1 && cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1]) < 0)
      --k;
    ch[k++] = ps[i];
  }
  for (int i = n - 2, t = k; i >= 0; i--) { // upper-hull
    while (k > t && cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1]) < 0)
      --k;
    ch[k++] = ps[i];
  }
  ch.resize(k - 1);
  return ch;
}

// O(nlogn)
void ccw_sort(ConvexPoly &ps) {
  const int n = ps.size();
  sort(ALL(ps));
  const P &O = ps[0];
  sort(ps.begin() + 1, ps.end(), [&O](const P &l, const P &r) -> bool {
    return cross(l - O, r - O) > 0;
  });
  int sr = 1;
  while (sr < n && cross(ps[sr] - O, ps[1] - O) == 0)
    sr++;
  sort(ps.begin() + 1, ps.begin() + sr, [&O](const P &l, const P &r) -> bool {
    return abs(l - O) < abs(r - O);
  });
  int el = n - 1;
  while (el - 1 >= 1 && cross(ps[el - 1] - O, ps[n - 1] - O) == 0)
    el--;
  sort(ps.begin() + el, ps.end(), [&O](const P &l, const P &r) -> bool {
    return abs(l - O) > abs(r - O);
  });
}
} // namespace Polys
using namespace Polys;
stringstream ss;
class Main {
public:
  void run() {
    int n;
    cin >> n;
    Poly poly;
    REP(i, n) {
      P p;
      cin >> p;
      poly.push_back(p);
    }
    ConvexPoly cp = convex_hull(poly);
    ccw_sort(cp);
    cout << cp.size() << endl;
    REP(i, cp.size()) { cout << (int)cp[i].X << " " << (int)cp[i].Y << endl; }
  }
};

int main() {
  cout << fixed << setprecision(20);
  cin.tie(0);
  ios::sync_with_stdio(false);
  Main().run();
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm> // other
#include <bitset>
#include <cassert> // c
#include <complex>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream> // io
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector> // container
using namespace std;

typedef int32_t i32;
typedef int64_t i64;
typedef i64 ll;
typedef uint32_t uint;
typedef uint64_t ull;

#define ALL(c) (begin(c)), (end(c))
#define REP(i, n) FOR(i, 0, n)
#define REPr(i, n) FORr(i, 0, n)
#define FOR(i, l, r) for (int i = (int)(l); i < (int)(r); ++i)
#define FORr(i, l, r) for (int i = (int)(r)-1; i >= (int)(l); --i)
#define EACH(it, o)                                                            \\
  for (__typeof((o).begin()) it = (o).begin(); it != (o).end(); ++it)
#define IN(l, v, r) ((l) <= (v) && (v) < (r))

// debug
#define DUMP(x) cerr << #x << " = " << (x)
#define DUMPLN(x) DUMP(x) << endl
#define DEBUG(x) DUMP(x) << LINE() << " " << __FILE__
#define DEBUGLN(x) DEBUG(x) << endl
#define LINE() cerr << " (L" << __LINE__ << ")"
#define LINELN() LINE() << endl
#define CHECK(exp, act)                                                        \\
  if (exp != act) {                                                            \\
    DUMPLN(exp);                                                               \\
    DEBUGLN(act);                                                              \\
  }
#define STOP(e)                                                                \\
  CHECK(e, true);                                                              \\
  if (!(e))                                                                    \\
    exit(1);

class range {
private:
  struct Iter {
    int v;
    int operator*() { return v; }
    bool operator!=(Iter &itr) { return v < itr.v; }
    void operator++() { ++v; }
  };
  Iter i, n;

public:
  range(int n) : i({0}), n({n}) {}
  range(int i, int n) : i({i}), n({n}) {}
  Iter &begin() { return i; }
  Iter &end() { return n; }
};

// output
template <typename T> ostream &operator<<(ostream &os, const vector<T> &as) {
  REP(i, as.size()) {
    if (i != 0)
      os << " ";
    os << as[i];
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<vector<T>> &as) {
  REP(i, as.size()) {
    if (i != 0)
      os << endl;
    os << as[i];
  }
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &ss) {
  EACH(a, ss) {
    if (a != ss.begin())
      os << " ";
    os << a;
  }
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename K, typename V>
ostream &operator<<(ostream &os, const map<K, V> &m) {
  bool isF = true;
  EACH(p, m) {
    if (!isF)
      os << endl;
    os << p;
    isF = false;
  }
  return os;
}

// input
char tmp[1000];
#define nextInt(n) scanf("%d", &n)
#define nextLong(n) scanf("%lld", &n) // I64d
#define nextDouble(n) scanf("%lf", &n)
#define nextChar(n) scanf("%c", &n)
#define nextString(n)                                                          \\
  scanf("%s", tmp);                                                            \\
  n = tmp

// values
template <class T> T INF() { assert(false); };
template <> int INF<int>() { return 1 << 28; };
template <> ll INF<ll>() { return 1LL << 58; };
template <> double INF<double>() { return 1e16; };

template <class T> T EPS() { assert(false); };
template <> int EPS<int>() { return 1; };
template <> ll EPS<ll>() { return 1LL; };
template <> double EPS<double>() { return 1e-8; };
template <> long double EPS<long double>() { return 1e-8; };

template <typename T> T pmod(T v, T M) { return (v % M + M) % M; }

namespace _double_tmpl {
typedef long double D;

static constexpr D Ae = 0;
D A(D a, D b) { return a + b; }
D Ainv(D a) { return -a; }
D S(D a, D b) { return A(a, Ainv(b)); }

static constexpr D Me = 1;
D M(D a, D b) { return a * b; }
D Minv(D a) { return 1.0 / a; };

int sig(D a, D b = 0) {
  return a < b - EPS<D>() ? -1 : a > b + EPS<D>() ? 1 : 0;
}
bool eq(D a, D b) { return sig(abs(a - b)) == 0; }

} // namespace _double_tmpl
using namespace _double_tmpl;
namespace Ps {
// using namespace _double_tmpl;
typedef complex<D> P, Vec;

#define X real()
#define Y imag()
istream &operator>>(istream &is, complex<D> &p) {
  D x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
bool eq(const P &a, const P &b) {
  return sig(a.real(), b.real()) == 0 && sig(a.imag(), b.imag()) == 0;
}
// a×b
D cross(const Vec &a, const Vec &b) { return imag(conj(a) * b); }
// a・b
D dot(const Vec &a, const Vec &b) { return real(conj(a) * b); }

int ccw(const P &a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS<D>())
    return +1; // counter clockwise
  if (cross(b, c) < -EPS<D>())
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;
}
} // namespace Ps
using namespace Ps;
namespace std {
bool operator<(const P &a, const P &b) {
  return make_pair(a.Y, a.X) < make_pair(b.Y, b.X);
  // return a.X != b.X ? a.X < b.X : a.Y < b.Y;
}
bool operator>(const P &a, const P &b) { return b < a; }
bool operator==(const P &a, const P &b) { return eq(a, b); }
}; // namespace std

namespace Polys {
typedef vector<P> Poly, ConvexPoly;

// O(nlogn)
ConvexPoly convex_hull(Poly ps) {
  int n = ps.size(), k = 0;
  sort(ALL(ps));
  Poly ch(2 * n);
  REP(i, n) { // lower-hull
    while (k > 1 && cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1]) < 0)
      --k;
    ch[k++] = ps[i];
  }
  for (int i = n - 2, t = k; i >= 0; i--) { // upper-hull
    while (k > t && cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1]) < 0)
      --k;
    ch[k++] = ps[i];
  }
  ch.resize(k - 1);
  return ch;
}

// O(nlogn)
void ccw_sort(ConvexPoly &ps) {
  const int n = ps.size();
  sort(ALL(ps));
  const P &O = ps[0];
  sort(ps.begin() + 1, ps.end(), [n, &O, &ps](const P &l, const P &r) -> bool {
    int cr = cross(l - O, r - O);
    if (cr != 0)
      return cr > 0;
    if (cross(r - O, ps[1] - O) == 0 && cross(l - O, ps[1] - O) == 0)
      return abs(l - O) < abs(r - O);
    if (cross(r - O, ps[n - 1] - O) == 0 && cross(l - O, ps[n - 1] - O) == 0)
      return abs(l - O) > abs(r - O);
    assert(false);
  });

  // sort(ALL(ps));
  // sort(ps.begin()+1,ps.end(),[&ps](const P& l,const P& r) -> bool{
  //     return cross(l-ps[0],r-ps[0]) > 0;
  // });
  // int sr=1;while(sr < n && cross(ps[sr]-ps[0],ps[1]-ps[0])==0)sr++;
  // sort(ps.begin(),ps.begin()+sr,[&ps](const P& l,const P& r) -> bool{return
  // abs(l-ps[0])<abs(r-ps[0]);}); int el=n-1;while(el-1 >=0 &&
  // cross(ps[el-1]-ps[0],ps[n-1]-ps[0])==0)el--;
  // sort(ps.begin()+el,ps.end(),[&ps](const P& l,const P& r) -> bool{return
  // abs(l-ps[0])>abs(r-ps[0]);});
}
} // namespace Polys
using namespace Polys;
stringstream ss;
class Main {
public:
  void run() {
    int n;
    cin >> n;
    Poly poly;
    REP(i, n) {
      P p;
      cin >> p;
      poly.push_back(p);
    }
    ConvexPoly cp = convex_hull(poly);
    ccw_sort(cp);
    cout << cp.size() << endl;
    REP(i, cp.size()) { cout << (int)cp[i].X << " " << (int)cp[i].Y << endl; }
  }
};

int main() {
  cout << fixed << setprecision(20);
  cin.tie(0);
  ios::sync_with_stdio(false);
  Main().run();
  return 0;
}