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

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

typedef long long int ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int>> vii;
#define rrep(i, m, n) for (int(i) = (m); (i) < (n); (i)++)
#define erep(i, m, n) for (int(i) = (m); (i) <= (n); (i)++)
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define rrev(i, m, n) for (int(i) = (n)-1; (i) >= (m); (i)--)
#define erev(i, m, n) for (int(i) = (n); (i) >= (m); (i)--)
#define rev(i, n) for (int(i) = (n)-1; (i) >= 0; (i)--)
#define vrep(i, c)                                                             \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ALL(v) (v).begin(), (v).end()
#define mp make_pair
#define pb push_back
template <class T, class S> inline bool minup(T &m, S x) {
  return m > (T)x ? (m = (T)x, true) : false;
}
template <class T, class S> inline bool maxup(T &m, S x) {
  return m < (T)x ? (m = (T)x, true) : false;
}

const int INF = 1000000000;
const ll MOD = 1000000007LL;
const double EPS = 1E-12;

struct Point : public complex<double> {
public:
  Point() {
    this->real(0);
    this->imag(0);
  }
  Point(const double &x, const double &y) {
    this->real(x);
    this->imag(y);
  }
  Point(const complex<double> w) {
    this->real(w.real());
    this->imag(w.imag());
  }
  inline double dot(Point p) { return (conj(*this) * p).real(); } // ??????
  inline double det(Point p) { return (conj(*this) * p).imag(); } // ??????
};

namespace std {
bool operator<(const Point &a, const Point &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (b.det(c) > 0.0)
    return 1;
  if (b.det(c) < 0.0)
    return -1;
  if (b.dot(c) < 0.0)
    return 2;
  if (norm(b) < norm(c))
    return -2;
  return 0;
}

typedef vector<Point> Polygon;

#define curr(P, i) P[(i) % P.size()]
#define next(P, i) P[(i + 1) % P.size()]
#define prev(P, i) P[(i + P.size() - 1) % P.size()]
bool isConvex(const Polygon &P) {
  for (int i = 0; i < P.size(); ++i)
    if (ccw(prev(P, i), curr(P, i), next(P, i)) > 0)
      return false;
  return true;
}

// O(nlogn)
vector<Point> AndrewMonotoneChain(vector<Point> ps) {
  int n = ps.size(), k = 0;
  sort(ps.begin(), ps.end());
  vector<Point> ch(2 * n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0)
      --k;
  for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0)
      --k;
  ch.resize(k - 1);
  return ch;
}

template <typename T> ostream &operator<<(ostream &r, const vector<T> t) {
  vrep(v, t) r << *v << (v + 1 == t.end() ? "" : " ");
  return r;
}
template <typename T>
ostream &operator<<(ostream &r, const pair<vector<T>, int> p) {
  int n = p.second;
  minup(n, p.first.size());
  rep(i, n - 1) r << p.first[i] << ' ';
  r << p.first[n - 1];
  return r;
}
template <typename T> ostream &operator<<(ostream &r, const pair<T *, int> p) {
  int n = p.second - 1;
  rep(i, n) r << p.first[i] << ' ';
  return r << p.first[n];
}
template <typename T, size_t S>
ostream &operator<<(ostream &r, const T (&a)[S]) {
  rep(i, S - 1) r << a[i] << ' ';
  return r << a[S - 1];
}

double x, y;
bool ok = true;

int main() {
  while (~scanf("%lf,%lf", &x, &y)) {
    Polygon P;
    P.pb(Point(x, y));
    rep(i, 3) {
      scanf(",%lf,%lf", &x, &y);
      P.pb(Point(x, y));
    }

    // cerr << P << endl;
    //     puts(isConvex(P) ? "NO" : "YES");
    //     puts(AndrewMonotoneChain(P) == P ? "YES" : "NO");
    vector<Point> res = AndrewMonotoneChain(P);
    sort(ALL(res));
    sort(ALL(P));
    puts(res == P ? "YES" : "NO");
  }

  return 0;
}

Error: 0
(0,0) (1,0) (1,1) (0,1)
(0,0) (3,0) (1,1) (1,3)


Fixed submission:

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

typedef long long int ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pair<int, int>> vii;
#define rrep(i, m, n) for (int(i) = (m); (i) < (n); (i)++)
#define erep(i, m, n) for (int(i) = (m); (i) <= (n); (i)++)
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define rrev(i, m, n) for (int(i) = (n)-1; (i) >= (m); (i)--)
#define erev(i, m, n) for (int(i) = (n); (i) >= (m); (i)--)
#define rev(i, n) for (int(i) = (n)-1; (i) >= 0; (i)--)
#define vrep(i, c)                                                             \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ALL(v) (v).begin(), (v).end()
#define mp make_pair
#define pb push_back
template <class T, class S> inline bool minup(T &m, S x) {
  return m > (T)x ? (m = (T)x, true) : false;
}
template <class T, class S> inline bool maxup(T &m, S x) {
  return m < (T)x ? (m = (T)x, true) : false;
}

const int INF = 1000000000;
const ll MOD = 1000000007LL;
const double EPS = 1E-12;

struct Point : public complex<double> {
public:
  Point() {
    this->real(0);
    this->imag(0);
  }
  Point(const double &x, const double &y) {
    this->real(x);
    this->imag(y);
  }
  Point(const complex<double> w) {
    this->real(w.real());
    this->imag(w.imag());
  }
  inline double dot(Point p) { return (conj(*this) * p).real(); } // ??????
  inline double det(Point p) { return (conj(*this) * p).imag(); } // ??????
};

namespace std {
bool operator<(const Point &a, const Point &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (b.det(c) > 0.0)
    return 1;
  if (b.det(c) < 0.0)
    return -1;
  if (b.dot(c) < 0.0)
    return 2;
  if (norm(b) < norm(c))
    return -2;
  return 0;
}

typedef vector<Point> Polygon;

#define curr(P, i) P[(i) % P.size()]
#define next(P, i) P[(i + 1) % P.size()]
#define prev(P, i) P[(i + P.size() - 1) % P.size()]
bool isConvex(const Polygon &P) {
  for (int i = 0; i < P.size(); ++i)
    if (ccw(prev(P, i), curr(P, i), next(P, i)) > 0)
      return false;
  return true;
}

// O(nlogn)
vector<Point> AndrewMonotoneChain(vector<Point> ps) {
  int n = ps.size(), k = 0;
  sort(ps.begin(), ps.end());
  vector<Point> ch(2 * n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0)
      --k;
  for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0)
      --k;
  ch.resize(k - 1);
  return ch;
}

template <typename T> ostream &operator<<(ostream &r, const vector<T> t) {
  vrep(v, t) r << *v << (v + 1 == t.end() ? "" : " ");
  return r;
}
template <typename T>
ostream &operator<<(ostream &r, const pair<vector<T>, int> p) {
  int n = p.second;
  minup(n, p.first.size());
  rep(i, n - 1) r << p.first[i] << ' ';
  r << p.first[n - 1];
  return r;
}
template <typename T> ostream &operator<<(ostream &r, const pair<T *, int> p) {
  int n = p.second - 1;
  rep(i, n) r << p.first[i] << ' ';
  return r << p.first[n];
}
template <typename T, size_t S>
ostream &operator<<(ostream &r, const T (&a)[S]) {
  rep(i, S - 1) r << a[i] << ' ';
  return r << a[S - 1];
}

double x, y;
bool ok = true;

int main() {
  while (~scanf("%lf,%lf", &x, &y)) {
    Polygon P;
    P.pb(Point(x, y));
    rep(i, 3) {
      scanf(",%lf,%lf", &x, &y);
      P.pb(Point(x, y));
    }

    cerr << P << endl;
    //    puts(isConvex(P) ? "NO" : "YES");
    puts(AndrewMonotoneChain(P) == P ? "YES" : "NO");
  }

  return 0;
}