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

/// Geometry INT

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

inline int sign(const LL x) {
  if (x < 0) {
    return -1;
  }
  if (x > 0) {
    return 1;
  }
  return 0;
}

struct point {
  LL x, y;
  point() {}
  point(LL _x, LL _y) : x(_x), y(_y) {}
};

bool operator<(const point &P, const point &Q) {
  if (P.y != Q.y) {
    return P.y < Q.y;
  }
  return P.x < Q.x;
}

bool operator==(const point &P, const point &Q) { return !(P < Q) && !(Q < P); }

struct compare_x {
  bool operator()(const point &P, const point &Q) {
    if (P.x != Q.x) {
      return P.x < Q.x;
    }
    return P.y < Q.y;
  }
};

void normalize(point &P) {
  assert(P.x != 0 || P.y != 0);
  LL g = __gcd(abs(P.x), abs(P.y));
  P.x /= g;
  P.y /= g;
  if (P.x < 0 || (P.x == 0 && P.y < 0)) {
    P.x = -P.x;
    P.y = -P.y;
  }
}

inline int half_plane(const point &P) {
  if (P.y != 0) {
    return sign(P.y);
  }
  return sign(P.x);
}

point operator+(const point &P, const point &Q) {
  return point(P.x + Q.x, P.y + Q.y);
}

point operator-(const point &P, const point &Q) {
  return point(P.x - Q.x, P.y - Q.y);
}

point operator*(const point &P, const LL k) { return point(P.x * k, P.y * k); }

point operator/(const point &P, const LL k) {
  assert(k != 0 && P.x % k == 0 && P.y % k == 0);
  return point(P.x / k, P.y / k);
}

inline LL dot(const point &P, const point &Q) { return P.x * Q.x + P.y * Q.y; }

inline LL cross(const point &P, const point &Q) {
  return P.x * Q.y - P.y * Q.x;
}

inline LL dist2(const point &P, const point &Q) {
  LL dx = P.x - Q.x;
  LL dy = P.y - Q.y;
  return dx * dx + dy * dy;
}

inline bool is_in(LL x, LL a, LL b) {
  if (a > b) {
    swap(a, b);
  }
  return (a <= x && x <= b);
}

inline bool is_in(const point &P, const point &A, const point &B) {
  if (cross(B - A, P - A) != 0) {
    return false;
  }
  return (is_in(P.x, A.x, B.x) && is_in(P.y, A.y, B.y));
}

inline bool segment_segment_intersect(const point &A, const point &B,
                                      const point &C, const point &D) {
  if (cross(B - A, D - C) == 0) { // lines are parallel
    return (is_in(A, C, D) || is_in(B, C, D) || is_in(C, A, B) ||
            is_in(D, A, B));
  }
  if (sign(cross(C - A, B - A)) * sign(cross(D - A, B - A)) > 0) {
    return false;
  }
  if (sign(cross(A - C, D - C)) * sign(cross(B - C, D - C)) > 0) {
    return false;
  }
  return true;
}

inline bool is_convex(const vector<point> &polygon) {
  int n = polygon.size();
  assert(n >= 3);
  for (int i = 0; i < n; i++) {
    int j = (i + 1) % n;
    int k = (i + 2) % n;
    if (sign(cross(polygon[j] - polygon[i], polygon[k] - polygon[i])) < 0) {
      return false;
    }
  }
  return true;
}

const int OUT = 0;
const int ON = 1;
const int IN = 2;
/// 0 outside, 1 boundary, 2 inside
inline int point_inside_polygon(const point &P, const vector<point> &polygon) {
  int n = polygon.size();
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    point A = polygon[i];
    point B = polygon[(i + 1) % n];
    if (is_in(P, A, B)) {
      return ON;
    }
    if (B.y < A.y) {
      swap(A, B);
    }
    if (P.y < A.y || B.y <= P.y || A.y == B.y) {
      continue;
    }
    if (sign(cross(B - A, P - A)) > 0) {
      cnt++;
    }
  }
  if (cnt & 1) {
    return IN;
  }
  return OUT;
}

struct compare_angle {
  point O;
  compare_angle() {}
  compare_angle(point _O) { O = _O; }
  bool operator()(const point &P, const point &Q) {
    if (half_plane(P - O) != half_plane(Q - O)) {
      return half_plane(P - O) < half_plane(Q - O);
    }
    int c = sign(cross(P - O, Q - O));
    if (c != 0) {
      return (c > 0);
    }
    return dist2(P, O) < dist2(Q, O);
  }
};

/// !!! no se como mantener los puntos colineales
vector<point> convex_hull_graham_scan(vector<point> pts) {
  sort(pts.begin(), pts.end());
  int n = pts.size();
  if (n <= 3) {
    return pts;
  }
  sort(++pts.begin(), pts.end(), compare_angle(pts[0]));

  cerr << "DEBUG\\n";
  for (int i = 0; i < n; i++) {
    cerr << pts[i].x << " " << pts[i].y << "\\n";
  }

  vector<point> ch(n);
  int top = 0;
  for (int i = 0; i < n; i++) {
    while (top >= 2 &&
           cross(ch[top - 1] - ch[top - 2], pts[i] - ch[top - 2]) < 0) {
      top--;
    }
    ch[top++] = pts[i];
  }
  ch.resize(top);
  return ch;
}

vector<point> convex_hull_monotone_chain(vector<point> pts) {
  sort(pts.begin(), pts.end());
  int n = pts.size();
  vector<point> ch(2 * n);
  int top = 0;
  for (int i = 0; i < n; i++) {
    while (top >= 2 &&
           cross(ch[top - 1] - ch[top - 2], pts[i] - ch[top - 2]) < 0) {
      top--;
    }
    ch[top++] = pts[i];
  }
  int size = top;
  for (int i = n - 2; i >= 0; i--) {
    while (top - size >= 1 &&
           cross(ch[top - 1] - ch[top - 2], pts[i] - ch[top - 2]) < 0) {
      top--;
    }
    ch[top++] = pts[i];
  }
  if (ch[0] == ch[top - 1]) {
    top--;
  }
  ch.resize(top);
  return ch;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
//  test OK
void test_segment_segment_intersection() {
  int q;
  cin >> q;
  while (q--) {
    point A, B, C, D;
    cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y;
    cout << (segment_segment_intersect(A, B, C, D) ? "1" : "0") << "\\n";
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
// test OK
void test_is_convex() {
  int n;
  cin >> n;
  vector<point> polygon(n);
  for (int i = 0; i < n; i++) {
    cin >> polygon[i].x >> polygon[i].y;
  }
  cout << (is_convex(polygon) ? "1" : "0") << "\\n";
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
// test OK
void test_point_inside_polygon() {
  int n;
  cin >> n;
  vector<point> polygon(n);
  for (int i = 0; i < n; i++) {
    cin >> polygon[i].x >> polygon[i].y;
  }
  int q;
  cin >> q;
  while (q--) {
    point P;
    cin >> P.x >> P.y;
    cout << point_inside_polygon(P, polygon) << "\\n";
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
// test ok
void test_parallel_orthogonal() {
  int q;
  cin >> q;
  while (q--) {
    point A, B, C, D;
    cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y;
    int answer = 0;
    if (cross(B - A, D - C) == 0) {
      answer = 2;
    } else if (dot(B - A, D - C) == 0) {
      answer = 1;
    }
    cout << answer << "\\n";
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
// test ???
void test_convex_hull() {
  int n;
  cin >> n;
  vector<point> pts(n);
  for (int i = 0; i < n; i++) {
    cin >> pts[i].x >> pts[i].y;
  }
  vector<point> answer = convex_hull_monotone_chain(pts);
  cout << answer.size() << "\\n";
  for (int i = 0; i < answer.size(); i++) {
    cout << answer[i].x << " " << answer[i].y << "\\n";
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  // test_segment_segment_intersection();
  // test_is_convex();
  // test_point_inside_polygon();
  // test_parallel_orthogonal();
  test_convex_hull();
}

Error: 0

Fixed submission:

/// Geometry INT

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

inline int sign(const LL x) {
  if (x < 0) {
    return -1;
  }
  if (x > 0) {
    return 1;
  }
  return 0;
}

struct point {
  LL x, y;
  point() {}
  point(LL _x, LL _y) : x(_x), y(_y) {}
};

bool operator<(const point &P, const point &Q) {
  if (P.y != Q.y) {
    return P.y < Q.y;
  }
  return P.x < Q.x;
}

bool operator==(const point &P, const point &Q) { return !(P < Q) && !(Q < P); }

struct compare_x {
  bool operator()(const point &P, const point &Q) {
    if (P.x != Q.x) {
      return P.x < Q.x;
    }
    return P.y < Q.y;
  }
};

void normalize(point &P) {
  assert(P.x != 0 || P.y != 0);
  LL g = __gcd(abs(P.x), abs(P.y));
  P.x /= g;
  P.y /= g;
  if (P.x < 0 || (P.x == 0 && P.y < 0)) {
    P.x = -P.x;
    P.y = -P.y;
  }
}

inline int half_plane(const point &P) {
  if (P.y != 0) {
    return sign(P.y);
  }
  return sign(P.x);
}

point operator+(const point &P, const point &Q) {
  return point(P.x + Q.x, P.y + Q.y);
}

point operator-(const point &P, const point &Q) {
  return point(P.x - Q.x, P.y - Q.y);
}

point operator*(const point &P, const LL k) { return point(P.x * k, P.y * k); }

point operator/(const point &P, const LL k) {
  assert(k != 0 && P.x % k == 0 && P.y % k == 0);
  return point(P.x / k, P.y / k);
}

inline LL dot(const point &P, const point &Q) { return P.x * Q.x + P.y * Q.y; }

inline LL cross(const point &P, const point &Q) {
  return P.x * Q.y - P.y * Q.x;
}

inline LL dist2(const point &P, const point &Q) {
  LL dx = P.x - Q.x;
  LL dy = P.y - Q.y;
  return dx * dx + dy * dy;
}

inline bool is_in(LL x, LL a, LL b) {
  if (a > b) {
    swap(a, b);
  }
  return (a <= x && x <= b);
}

inline bool is_in(const point &P, const point &A, const point &B) {
  if (cross(B - A, P - A) != 0) {
    return false;
  }
  return (is_in(P.x, A.x, B.x) && is_in(P.y, A.y, B.y));
}

inline bool segment_segment_intersect(const point &A, const point &B,
                                      const point &C, const point &D) {
  if (cross(B - A, D - C) == 0) { // lines are parallel
    return (is_in(A, C, D) || is_in(B, C, D) || is_in(C, A, B) ||
            is_in(D, A, B));
  }
  if (sign(cross(C - A, B - A)) * sign(cross(D - A, B - A)) > 0) {
    return false;
  }
  if (sign(cross(A - C, D - C)) * sign(cross(B - C, D - C)) > 0) {
    return false;
  }
  return true;
}

inline bool is_convex(const vector<point> &polygon) {
  int n = polygon.size();
  assert(n >= 3);
  for (int i = 0; i < n; i++) {
    int j = (i + 1) % n;
    int k = (i + 2) % n;
    if (sign(cross(polygon[j] - polygon[i], polygon[k] - polygon[i])) < 0) {
      return false;
    }
  }
  return true;
}

const int OUT = 0;
const int ON = 1;
const int IN = 2;
/// 0 outside, 1 boundary, 2 inside
inline int point_inside_polygon(const point &P, const vector<point> &polygon) {
  int n = polygon.size();
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    point A = polygon[i];
    point B = polygon[(i + 1) % n];
    if (is_in(P, A, B)) {
      return ON;
    }
    if (B.y < A.y) {
      swap(A, B);
    }
    if (P.y < A.y || B.y <= P.y || A.y == B.y) {
      continue;
    }
    if (sign(cross(B - A, P - A)) > 0) {
      cnt++;
    }
  }
  if (cnt & 1) {
    return IN;
  }
  return OUT;
}

struct compare_angle {
  point O;
  compare_angle() {}
  compare_angle(point _O) { O = _O; }
  bool operator()(const point &P, const point &Q) {
    if (half_plane(P - O) != half_plane(Q - O)) {
      return half_plane(P - O) < half_plane(Q - O);
    }
    int c = sign(cross(P - O, Q - O));
    if (c != 0) {
      return (c > 0);
    }
    return dist2(P, O) < dist2(Q, O);
  }
};

/// !!! no se como mantener los puntos colineales
vector<point> convex_hull_graham_scan(vector<point> pts) {
  sort(pts.begin(), pts.end());
  int n = pts.size();
  if (n <= 3) {
    return pts;
  }
  sort(++pts.begin(), pts.end(), compare_angle(pts[0]));

  cerr << "DEBUG\\n";
  for (int i = 0; i < n; i++) {
    cerr << pts[i].x << " " << pts[i].y << "\\n";
  }

  vector<point> ch(n);
  int top = 0;
  for (int i = 0; i < n; i++) {
    while (top >= 2 &&
           cross(ch[top - 1] - ch[top - 2], pts[i] - ch[top - 2]) < 0) {
      top--;
    }
    ch[top++] = pts[i];
  }
  ch.resize(top);
  return ch;
}

vector<point> convex_hull_monotone_chain(vector<point> pts) {
  sort(pts.begin(), pts.end());
  int n = pts.size();
  if (n <= 3) {
    sort(++pts.begin(), pts.end(), compare_angle(pts[0]));
  }
  vector<point> ch(n);
  int top = 0;
  for (int i = 0; i < n; i++) {
    while (top >= 2 &&
           cross(ch[top - 1] - ch[top - 2], pts[i] - ch[top - 2]) < 0) {
      top--;
    }
    ch[top++] = pts[i];
  }
  int size = top;
  for (int i = n - 2; i >= 0; i--) {
    while (top - (size - 1) >= 2 &&
           cross(ch[top - 1] - ch[top - 2], pts[i] - ch[top - 2]) < 0) {
      top--;
    }
    ch[top++] = pts[i];
  }
  if (ch[0] == ch[top - 1]) {
    top--;
  }
  ch.resize(top);
  return ch;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
//  test OK
void test_segment_segment_intersection() {
  int q;
  cin >> q;
  while (q--) {
    point A, B, C, D;
    cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y;
    cout << (segment_segment_intersect(A, B, C, D) ? "1" : "0") << "\\n";
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
// test OK
void test_is_convex() {
  int n;
  cin >> n;
  vector<point> polygon(n);
  for (int i = 0; i < n; i++) {
    cin >> polygon[i].x >> polygon[i].y;
  }
  cout << (is_convex(polygon) ? "1" : "0") << "\\n";
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
// test OK
void test_point_inside_polygon() {
  int n;
  cin >> n;
  vector<point> polygon(n);
  for (int i = 0; i < n; i++) {
    cin >> polygon[i].x >> polygon[i].y;
  }
  int q;
  cin >> q;
  while (q--) {
    point P;
    cin >> P.x >> P.y;
    cout << point_inside_polygon(P, polygon) << "\\n";
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
// test ok
void test_parallel_orthogonal() {
  int q;
  cin >> q;
  while (q--) {
    point A, B, C, D;
    cin >> A.x >> A.y >> B.x >> B.y >> C.x >> C.y >> D.x >> D.y;
    int answer = 0;
    if (cross(B - A, D - C) == 0) {
      answer = 2;
    } else if (dot(B - A, D - C) == 0) {
      answer = 1;
    }
    cout << answer << "\\n";
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
// test ???
void test_convex_hull() {
  int n;
  cin >> n;
  vector<point> pts(n);
  for (int i = 0; i < n; i++) {
    cin >> pts[i].x >> pts[i].y;
  }
  vector<point> answer = convex_hull_monotone_chain(pts);
  cout << answer.size() << "\\n";
  for (int i = 0; i < answer.size(); i++) {
    cout << answer[i].x << " " << answer[i].y << "\\n";
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  // test_segment_segment_intersection();
  // test_is_convex();
  // test_point_inside_polygon();
  // test_parallel_orthogonal();
  test_convex_hull();
}