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

#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
#include <vector>
namespace lc {
static const double EPS = 1e-9;
}
namespace lc {
struct Point {
  double x;
  double y;
  explicit Point(const double &x = 0.0, const double &y = 0.0) : x(x), y(y) {}
  Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
  Point &operator+=(const Point &p) { return *this = *this + p; }
  Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
  Point operator*(double s) const { return Point(x * s, y * s); }
  bool operator==(const Point &p) const { return x == p.x && y == p.y; }
  bool operator<(const Point &p) const {
    return (x == p.x) ? (y < p.y) : (x < p.x);
  }
  double abs() const { return sqrt(x * x + y * y); }
  double norm() const { return x * x + y * y; }
};
inline Point operator*(double s, const Point &p) { return p * s; }
inline double cross(const Point &a, const Point &b) {
  return a.x * b.y - a.y * b.x;
}
inline double dot(const Point &a, const Point &b) {
  return a.x * b.x + a.y * b.y;
}
inline int ccw(const Point &a, const Point &b, const Point &c) {
  Point d = b - a, e = c - a;
  if (cross(d, e) > 0.0) {
    return 1;
  }
  if (cross(d, e) < 0.0) {
    return -1;
  }
  if (dot(d, e) < 0.0) {
    return 2;
  }
  if (d.abs() < e.abs()) {
    return -2;
  }
  return 0;
}
} // namespace lc
namespace lc {
struct Line {
  Point a;
  Point b;
  explicit Line(const Point &a = Point(), const Point &b = Point())
      : a(a), b(b) {}
  Point projection(const Point &p) const {
    double t = dot(p - a, b - a) / (b - a).norm();
    return a + t * (b - a);
  }
};
} // namespace lc
namespace lc {
class Polygon {
private:
  std::vector<Point> m_points;

public:
  Polygon() : m_points() {}
  explicit Polygon(size_t s, const Point &p = Point()) : m_points(s, p) {}
  template <typename Iterator>
  explicit Polygon(Iterator begin, Iterator end) : m_points(begin, end) {}
  explicit Polygon(std::initializer_list<Point> init) : m_points(init) {}
  const Point &operator[](int i) const { return m_points[i]; }
  Point &operator[](int i) { return m_points[i]; }
  int size() const { return static_cast<int>(m_points.size()); }
  int contains(const Point &p) const {
    int result = -1;
    for (int i = 0; i < size(); ++i) {
      Point a = m_points[i] - p;
      Point b = m_points[(i + 1) % size()] - p;
      if (a.y > b.y) {
        std::swap(a, b);
      }
      if (a.y <= 0.0 && b.y > 0.0 && cross(a, b) < 0.0) {
        result = -result;
      }
      if (cross(a, b) == 0.0 && dot(a, b) <= 0.0) {
        return 0;
      }
    }
    return result;
  }
};
} // namespace lc
namespace lc {
inline Polygon convex_hull(const std::vector<Point> &points) {
  const int n = points.size();
  std::vector<Point> ps(points);
  std::sort(ps.begin(), ps.end());
  std::vector<Point> ch(2 * n);
  int k = 0;
  for (int i = 0; i < n; ch[k++] = ps[i++]) {
    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--]) {
    while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) {
      --k;
    }
  }
  ch.resize(k - 1);
  return Polygon(ch.begin(), ch.end());
}
} // namespace lc
namespace lc {
class Visualizer {
private:
  double m_scale;
  double m_offset_x;
  double m_offset_y;

public:
  explicit Visualizer(double scale = 1.0, double offset_x = 0.0,
                      double offset_y = 0.0)
      : m_scale(scale), m_offset_x(offset_x), m_offset_y(offset_y) {}
};
} // namespace lc
using namespace std;
static const double EPS = lc::EPS;
static const lc::Point DIR_TABLE[4] = {lc::Point(1.0, 0.0), lc::Point(0.0, 1.0),
                                       lc::Point(-1.0, 0.0),
                                       lc::Point(0.0, -1.0)};
int main() {
  ios_base::sync_with_stdio(false);
  cout << setiosflags(ios::fixed) << setprecision(10);
  lc::Visualizer vis(1.0, 0.0, 0.0);
  while (true) {
    int m, n;
    cin >> m >> n;
    if (m == 0 && n == 0) {
      break;
    }
    vector<lc::Point> segments(m), polls(n * 4);
    for (int i = 0; i < m; ++i) {
      cin >> segments[i].x >> segments[i].y;
    }
    for (int i = 0; i < n; ++i) {
      double x, y;
      cin >> x >> y;
      polls[i * 4 + 0] = lc::Point(x, y) + DIR_TABLE[0] * 10.0 * EPS;
      polls[i * 4 + 1] = lc::Point(x, y) + DIR_TABLE[1] * 10.0 * EPS;
      polls[i * 4 + 2] = lc::Point(x, y) + DIR_TABLE[2] * 10.0 * EPS;
      polls[i * 4 + 3] = lc::Point(x, y) + DIR_TABLE[3] * 10.0 * EPS;
    }
    while (true) {
      bool modified = false;
      segments.erase(unique(segments.begin(), segments.end()), segments.end());
      vector<lc::Point> next;
      next.clear();
      for (size_t i = 0; i < segments.size(); ++i) {
        next.push_back(segments[i]);
        if (i + 2 >= segments.size()) {
          continue;
        }
        if ((segments[i + 2] - segments[i]).abs() < 2.0 * EPS) {
          continue;
        }
        lc::Polygon tri({segments[i], segments[i + 1], segments[i + 2]});
        for (size_t j = 0; j < polls.size(); ++j) {
          const auto &p = polls[j];
          if (tri[1] == p) {
            tri[1] += DIR_TABLE[j % 4] * EPS;
          }
        }
        vector<lc::Point> pts({segments[i], segments[i + 2]});
        for (size_t j = 0; j < polls.size(); ++j) {
          const auto &p = polls[j];
          const int contains = tri.contains(p);
          if (contains > 0) {
            pts.push_back(p);
          } else if (contains == 0) {
            const auto &dir = DIR_TABLE[j % 4];
            const auto proj =
                lc::Line(segments[i], segments[i + 2]).projection(p);
            if (lc::dot(proj - p, dir) < 0.0) {
              pts.push_back(p);
            }
          }
        }
        const lc::Polygon conv = convex_hull(pts);
        int locs[3] = {-1, -1, -1};
        for (int j = 0; j < conv.size(); ++j) {
          for (int k = 0; k < 3; ++k) {
            if (segments[i + k] == conv[j]) {
              locs[k] = j;
            }
          }
        }
        if (locs[1] < 0) {
          const int t = conv.size();
          const int d = ((locs[0] + 1) % t == locs[2]) ? -1 : 1;
          for (int j = locs[0]; j != locs[2]; j = (j + d + t) % t) {
            next.push_back(conv[j]);
          }
          modified = true;
          for (size_t j = i + 2; j < segments.size(); ++j) {
            next.push_back(segments[j]);
          }
          break;
        } else {
          next.push_back(segments[i]);
        }
      }
      if (!modified) {
        break;
      }
      segments.swap(next);
    }
    double answer = 0.0;
    for (size_t i = 0; i + 1 < segments.size(); ++i) {
      answer += (segments[i + 1] - segments[i]).abs();
    }
    cout << answer << endl;
  }
  return 0;
}

Error: -8

Fixed submission:

#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
#include <vector>

using namespace std;

const double EPS = 1e-9;

bool tolerant_eq(double a, double b) { return abs(a - b) < EPS; }

struct Point {
  double x, y;
  explicit Point(const double &x = 0.0, const double &y = 0.0) : x(x), y(y) {}

  static Point invalid() {
    double qnan = numeric_limits<double>::quiet_NaN();
    return Point(qnan, qnan);
  }
  bool is_valid() const { return !(isnan(x) || isnan(y)); }

  Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
  Point &operator+=(const Point &p) { return *this = *this + p; }
  Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
  Point &operator-=(const Point &p) { return *this = *this - p; }
  Point operator*(double s) const { return Point(x * s, y * s); }
  Point &operator*=(double s) { return *this = *this * s; }
  Point operator/(double s) const { return Point(x / s, y / s); }
  Point &operator/=(double s) { return *this = *this / s; }

  bool operator==(const Point &p) const { return x == p.x && y == p.y; }
  bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
  bool operator<(const Point &p) const {
    return (x == p.x) ? (y < p.y) : (x < p.x);
  }
};

Point operator*(double s, const Point &p) { return p * s; }

bool tolerant_eq(const Point &a, const Point &b) {
  return tolerant_eq(a.x, b.x) && tolerant_eq(a.y, b.y);
}
double abs(const Point &p) { return sqrt(p.x * p.x + p.y * p.y); }
Point unit(const Point &p) { return p / abs(p); }
Point ortho(const Point &p) { return Point(-p.y, p.x); }
double cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
int ccw(const Point &a, const Point &b, const Point &c) {
  Point d = b - a, e = c - a;
  if (cross(d, e) > 0.0) {
    return 1;
  }
  if (cross(d, e) < 0.0) {
    return -1;
  }
  if (dot(d, e) < 0.0) {
    return 2;
  }
  if (abs(d) < abs(e)) {
    return -2;
  }
  return 0;
}

struct Polygon : public vector<Point> {
  Polygon() : vector<Point>() {}
  explicit Polygon(size_t s, const Point &p = Point()) : vector<Point>(s, p) {}

  static Polygon invalid() { return Polygon(); }
  bool is_valid() const { return size() > 0; }
};

Polygon convex_hull(vector<Point> p) {
  int n = p.size(), k = 0;
  sort(p.begin(), p.end());
  Polygon res(2 * n);
  for (int i = 0; i < n; ++i, ++k) {
    while (k >= 2 && ccw(res[k - 2], res[k - 1], p[i]) <= 0) {
      --k;
    }
    res[k] = p[i];
  }
  for (int i = n - 2, t = k + 1; i >= 0; --i, ++k) {
    while (k >= t && ccw(res[k - 2], res[k - 1], p[i]) <= 0) {
      --k;
    }
    res[k] = p[i];
  }
  res.resize(k - 1);
  return res;
}

int convex_contains(const Polygon &g, const Point &p) {
  int n = g.size();
  Point q = (g[0] + g[n / 2] + g[2 * n / 3]) / 3.0;
  int left = 0, right = n;
  while (left + 1 < right) {
    int c = (left + right) / 2;
    Point p_q = p - q, c_q = g[c] - q;
    if (cross(g[left] - q, c_q) > 0.0) {
      if (cross(g[left] - q, p_q) > 0.0 && cross(c_q, p_q) < 0.0) {
        right = c;
      } else {
        left = c;
      }
    } else {
      if (cross(g[left] - q, p_q) < 0.0 && cross(c_q, p_q) < 0.0) {
        left = c;
      } else {
        right = c;
      }
    }
  }
  right %= n;
  if (cross(g[left] - p, g[right] - p) < 0.0) {
    return 0;
  } // out
  if (cross(g[left] - p, g[right] - p) > 0.0) {
    return -1;
  }          // in
  return -1; // on line
}

int main() {
  ios_base::sync_with_stdio(false);
  cout << setiosflags(ios::fixed) << setprecision(10);
  while (true) {
    int m, n;
    cin >> m >> n;
    if (m == 0 && n == 0) {
      break;
    }
    vector<Point> init(m), poll(n * 3);
    for (int i = 0; i < m; ++i) {
      cin >> init[i].x >> init[i].y;
    }
    for (int i = 0; i < n; ++i) {
      cin >> poll[i].x >> poll[i].y;
      poll[i + n] = poll[i] + Point(2 * EPS, 0.0);
      poll[i + n + n] = poll[i] + Point(EPS, EPS);
    }
    n *= 3;
    vector<Point> fixed(1, init[0]);
    vector<int> fccw(1, 0);
    for (int i = 1; i + 1 < m; ++i) {
      vector<Point> pollArea(3);
      pollArea[0] = fixed.back();
      pollArea[1] = init[i];
      pollArea[2] = init[i + 1];
      Polygon triangle = convex_hull(pollArea);
      vector<Point> cand;
      cand.push_back(fixed.back());
      cand.push_back(init[i + 1]);
      for (int j = 0; j < n; ++j) {
        if (convex_contains(triangle, poll[j])) {
          cand.push_back(poll[j]);
        }
      }
      if (cand.size() == 0) {
        continue;
      }
      Polygon convex = convex_hull(cand);
      int cs = convex.size(), k = 0;
      for (int j = 0; j < cs; ++j) {
        if (convex[j] == fixed.back()) {
          k = j;
          break;
        }
      }
      if (convex[(k + 1) % cs] == init[i + 1]) {
        int begin = (k + cs - 1) % cs, end = (k + 1) % cs;
        for (int j = begin; j != end; j = (j + cs - 1) % cs) {
          fixed.push_back(convex[j]);
          fccw.push_back(-1);
        }
      } else {
        int begin = (k + 1) % cs, end = (k + cs - 1) % cs;
        for (int j = begin; j != end; j = (j + 1) % cs) {
          fixed.push_back(convex[j]);
          fccw.push_back(1);
        }
      }
    }
    fixed.push_back(init.back());
    fccw.push_back(0);
    while (true) {
      vector<Point> nfixed(1, fixed[0]);
      vector<int> nfccw(1, 0);
      bool modified = false;
      for (int i = 1; i + 1 < fixed.size(); ++i) {
        Point a = nfixed.back(), b = fixed[i], c = fixed[i + 1];
        if (fccw[i] == ccw(a, b, c)) {
          nfixed.push_back(b);
          nfccw.push_back(fccw[i]);
          continue;
        }
        modified = true;
        vector<Point> pollArea(3);
        pollArea[0] = a;
        pollArea[1] = b;
        pollArea[2] = c;
        Polygon triangle = convex_hull(pollArea);
        vector<Point> cand;
        for (int j = 0; j < m; ++j) {
          if (convex_contains(triangle, poll[j])) {
            cand.push_back(poll[j]);
          }
        }
        if (cand.size() == 0) {
          continue;
        }
        Polygon convex = convex_hull(cand);
        int k = 0, cs = convex.size();
        for (int j = 0; j < cs; ++j) {
          if (convex[j] == a) {
            k = j;
            break;
          }
        }
        if (convex[(k + 1) % cs] == c) {
          int begin = (k + cs - 1) % cs;
          for (int j = begin; j != begin; j = (j + cs - 1) % cs) {
            nfixed.push_back(convex[j]);
            nfccw.push_back(-1);
          }
        } else {
          int begin = (k + 1) % cs;
          for (int j = begin; j != begin; j = (j + 1) % cs) {
            nfixed.push_back(convex[j]);
            nfccw.push_back(1);
          }
        }
      }
      nfixed.push_back(fixed.back());
      nfccw.push_back(0);
      if (!modified) {
        break;
      }
      fixed = nfixed;
      fccw = nfccw;
    }
    double answer = 0.0;
    for (int i = 1; i < fixed.size(); ++i) {
      answer += abs(fixed[i] - fixed[i - 1]);
    }
    cout << answer << endl;
  }
  return 0;
}