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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll, ll> pll;
typedef long double D;
typedef complex<D> P;
#define F first
#define S second
const ll E = 1e18 + 7;
const ll MOD = 1000000007;

template <typename T, typename U>
istream &operator>>(istream &i, pair<T, U> &A) {
  i >> A.F >> A.S;
  return i;
}
template <typename T> istream &operator>>(istream &i, vector<T> &A) {
  for (auto &I : A) {
    i >> I;
  }
  return i;
}
template <typename T, typename U>
ostream &operator<<(ostream &o, pair<T, U> &A) {
  o << A.F << " " << A.S;
  return o;
}
template <typename T> ostream &operator<<(ostream &o, vector<T> &A) {
  ll i = A.size();
  for (auto &I : A) {
    o << I << (--i ? " " : "");
  }
  return o;
}
template <typename T> vector<T> &cset(vector<T> &A, T e = T()) {
  for (auto &I : A) {
    I = e;
  }
  return A;
}

namespace Geometry {
typedef long double D;
typedef complex<long double> P;
typedef pair<P, D> C;

const D EPS = 1e-9;
const D PI = asin(1) * 2;
const D INF = 1e18;

const static bool comp(const P &p1, const P &p2) {
  return p1.real() == p2.real() ? p1.imag() < p2.imag() : p1.real() < p2.real();
}

static bool comp_y(const P &p1, const P &p2) {
  return p1.imag() == p2.imag() ? p1.real() < p2.real() : p1.imag() < p2.imag();
}

static bool eqls(const P &p1, const P &p2) { return abs(p1 - p2) < EPS; }

D dot(P p1, P p2) { return p1.real() * p2.real() + p1.imag() * p2.imag(); }

D cross(P p1, P p2) { return p1.real() * p2.imag() - p1.imag() * p2.real(); }

P project(P vec, P x) { return vec * (x / vec).real(); }

P project(P p1, P p2, P x) { return p1 + project(p2 - p1, x - p1); }

P reflect(P vec, P x) { return vec * conj(x / vec); }

P reflect(P p1, P p2, P x) { return p1 + reflect(p2 - p1, x - p1); }

bool intersectSL(P p1, P p2, P vec) {
  vec /= abs(vec);
  p1 /= vec;
  p2 /= vec;
  return (p1.imag() < EPS && p2.imag() > -EPS) ||
         (p1.imag() > -EPS && p2.imag() < EPS);
}

bool intersectSL(P p1, P p2, P p3, P p4) {
  return intersectSL(p1 - p4, p2 - p4, p3 - p4);
}

bool intersectSS(P p1, P p2, P p3, P p4) {
  return (dot(p2 - p1, p3 - p1) < -EPS && dot(p2 - p1, p4 - p1) < -EPS) ||
                 (dot(p1 - p2, p3 - p2) < -EPS && dot(p1 - p2, p4 - p2) < -EPS)
             ? false
             : intersectSL(p1, p2, p3, p4) && intersectSL(p3, p4, p1, p2);
}

D distLP(P vec, P x) { return abs((x / vec).imag()) * abs(vec); }

D distLP(P p1, P p2, P x) { return distLP(p2 - p1, x - p1); }

D distSP(P p1, P p2, P x) {
  return dot(p2 - p1, x - p1) < -EPS   ? abs(x - p1)
         : dot(p1 - p2, x - p2) < -EPS ? abs(x - p2)
                                       : distLP(p1, p2, x);
}

D distSS(P p1, P p2, P p3, P p4) {
  return intersectSS(p1, p2, p3, p4)
             ? 0.0
             : min(min(distSP(p1, p2, p3), distSP(p1, p2, p4)),
                   min(distSP(p3, p4, p1), distSP(p3, p4, p2)));
}

P crosspointLL(P p1, P p2, P vec) {
  return abs(cross(p2 - p1, vec)) < EPS
             ? vec
             : vec * cross(p2 - p1, p2) / cross(p2 - p1, vec);
}

P crosspointLL(P p1, P p2, P p3, P p4) {
  return p4 + crosspointLL(p1 - p4, p2 - p4, p3 - p4);
}

P crosspointSS(P p1, P p2, P p3, P p4) {
  return distSP(p1, p2, p3) < EPS   ? p3
         : distSP(p1, p2, p4) < EPS ? p4
                                    : crosspointLL(p1, p2, p3, p4);
}

bool intersectShL(P p1, P p2, P vec) {
  vec /= abs(vec);
  return intersectSL(p1, p2, vec) &&
         crosspointLL(p1 / vec, p2 / vec, vec / vec).real() > -EPS;
}

bool intersectShL(P p1, P p2, P p3, P p4) {
  return intersectShL(p1 - p3, p2 - p3, p4 - p3);
}

// 1::in,0::on edge,-1::out
int contain(const vector<P> &poly, const P &p) {
  vector<P> A = {{65537, 96847},
                 {-24061, 6701},
                 {56369, -86509},
                 {-93763, -78049},
                 {56957, 10007}};
  vector<bool> cnt(5, false);
  for (int i = 1; i <= poly.size(); i++) {
    if (distSP(poly[i - 1], poly[i % poly.size()], p) < EPS) {
      return 0;
    }
    for (int j = 0; j < 5; j++) {
      if (intersectShL(poly[i - 1], poly[i % poly.size()], p, p + A[j])) {
        cnt[j] = !cnt[j];
      }
    }
  }
  int in = 0;
  for (int j = 0; j < 5; j++) {
    if (cnt[j]) {
      in++;
    }
  }
  return in >= 3 ? 1 : -1;
}

vector<P> convexcut(const vector<P> &poly, P p1, P p2) {
  vector<P> ret;
  for (int i = 1; i <= poly.size(); i++) {
    if (cross(p2 - p1, poly[i - 1] - p1) > -EPS) {
      ret.push_back(poly[i - 1]);
    }
    if (intersectSL(poly[i - 1], poly[i % poly.size()], p1, p2) &&
        distLP(p1, p2, poly[i - 1]) > EPS &&
        distLP(p1, p2, poly[i % poly.size()]) > EPS) {
      ret.push_back(crosspointLL(poly[i - 1], poly[i % poly.size()], p1, p2));
    }
  }
  return ret;
}

D area(const vector<P> &poly) {
  D ans = 0;
  for (int i = 2; i < poly.size(); i++) {
    ans += cross(poly[i - 1] - poly[0], poly[i] - poly[0]);
  }
  return abs(ans) / 2;
}

vector<P> convexhull(vector<P> pts) {
  vector<P> ret;
  sort(pts.begin(), pts.end(), comp);
  for (auto &I : pts) {
    if (!ret.empty() && I == ret.back()) {
      continue;
    }
    while (ret.size() >= 2 &&
           cross(ret.back() - ret[ret.size() - 2], I - ret.back()) < -EPS) {
      ret.pop_back();
    }
    ret.push_back(I);
  }
  reverse(pts.begin(), pts.end());
  for (auto &I : pts) {
    if (!ret.empty() && I == ret.back()) {
      continue;
    }
    while (ret.size() >= 2 &&
           cross(ret.back() - ret[ret.size() - 2], I - ret.back()) < -EPS) {
      ret.pop_back();
    }
    ret.push_back(I);
  }
  if (ret[0] == ret.back()) {
    ret.pop_back();
  }
  return ret;
}

// 4::seperate,3::circumscribe,2::intersect,1::inscribe,0::contain,-1::same
int intersectCC(C c1, C c2) {
  D d = abs(c1.F - c2.F), r = c1.S + c2.S, dif = abs(c2.S - c1.S);
  if (d < EPS && dif < EPS) {
    return -1;
  }
  if (d - r > EPS) {
    return 4;
  }
  if (d - r > -EPS) {
    return 3;
  }
  if (d - dif > EPS) {
    return 2;
  }
  if (d - dif > -EPS) {
    return 1;
  }
  return 0;
}

vector<P> crosspointLC(P p1, P p2, C c) {
  vector<P> ret;
  P pr = project(p1, p2, c.F);
  D d = distLP(p1, p2, c.F);
  if (d - c.S > EPS) {
    return ret;
  }
  if (d - c.S > -EPS) {
    ret.push_back(pr);
    return ret;
  }
  P vec = p2 - p1;
  vec *= sqrt(c.S * c.S - d * d) / abs(vec);
  ret.push_back(pr - vec);
  ret.push_back(pr + vec);
  return ret;
}

vector<P> crosspointSC(P p1, P p2, C c) {
  vector<P> ret;
  for (auto &I : crosspointLC(p1, p2, c)) {
    if (distSP(p1, p2, I) < EPS) {
      ret.push_back(I);
    }
  }
  return ret;
}

vector<P> crosspointCC(C c1, C c2) {
  vector<P> ret;
  P vec = c2.F - c1.F;
  D base = (c1.S * c1.S + norm(vec) - c2.S * c2.S) / (2 * abs(vec));
  D h = sqrt(c1.S * c1.S - base * base);
  vec /= abs(vec);
  ret.push_back(c1.F + vec * P(base, -h));
  ret.push_back(c1.F + vec * P(base, h));
  return ret;
}

vector<P> tangentCP(C c, P p) {
  return crosspointCC(c, C(p, sqrt(norm(c.F - p) - c.S * c.S)));
}

vector<pair<P, P>> tangentCC(C c1, C c2) {
  vector<pair<P, P>> ret;
  P d = c2.F - c1.F;
  for (D i : {-1, 1}) {
    D r = c1.S + c2.S * i;
    if (intersectCC(c1, c2) > i + 1) {
      for (P s : {-1i, 1i}) {
        P p = r + s * sqrt(norm(d) - norm(r));
        ret.push_back(
            {c1.F + d * c1.S / norm(d) * p, c2.F - d * i * c2.S / norm(d) * p});
      }
    }
  }
  return ret;
}

D area(const vector<P> &poly, C c) {
  D ret = 0;
  for (int i = 0; i < poly.size(); i++) {
    P a = poly[i] - c.F, b = poly[(i + 1) % poly.size()] - c.F;
    if (abs(a) < c.S + EPS && abs(b) < c.S + EPS) {
      ret += cross(a, b);
    } else {
      vector<P> A = crosspointSC(a, b, {0, c.S});
      if (A.empty()) {
        ret += c.S * c.S * arg(b / a);
      } else {
        ret += (abs(a) < c.S ? cross(a, A[0]) : c.S * c.S * arg(A[0] / a));
        ret +=
            (abs(b) < c.S ? cross(A.back(), b) : c.S * c.S * arg(b / A.back()));
        ret += cross(A[0], A.back());
      }
    }
  }
  return abs(ret) / 2;
}

// 反時計回り
D diameter(const vector<P> &poly) {
  D ret = 0;
  ll l = 0, r = 0, n = poly.size();
  if (n == 2) {
    return abs(poly[0] - poly[1]);
  }
  for (int i = 0; i < n; i++) {
    if (comp(poly[l], poly[i])) {
      l = i;
    }
    if (comp(poly[i], poly[r])) {
      r = i;
    }
  }
  ll sl = r, sr = l;
  while (sl != l || sr != r) {
    ret = max(ret, abs(poly[r] - poly[l]));
    if (cross(poly[(l + 1) % n] - poly[l], poly[(r + 1) % n] - poly[r]) < 0) {
      (++l) %= n;
    } else {
      (++r) %= n;
    }
  }
  return ret;
}

D closestpair(vector<P> pt) {
  sort(pt.begin(), pt.end(), comp);
  D ret = INF;
  for (ll i = 1; i < pt.size(); i <<= 1) {
    for (ll j = 0; i + j < pt.size(); j += i * 2) {
      ll m = i + j;
      vector<P> R;
      D l = -INF, r = INF;
      for (ll k = j; k < m; k++) {
        l = max(l, pt[k].real());
      }
      for (ll k = 0; m + k < pt.size() && k < i; k++) {
        r = min(r, pt[m + k].real());
      }
      for (ll k = 0; m + k < pt.size() && k < i; k++) {
        if (pt[m + k].real() - l < ret) {
          R.push_back(pt[m + k]);
        }
      }
      ll idx = 0;
      for (ll k = j; k < m; k++) {
        if (r - pt[k].real() > ret) {
          continue;
        }
        while (idx < R.size() && pt[k].imag() - R[idx].imag() > ret) {
          idx++;
        }
        for (ll n = idx; n < R.size() && R[n].imag() - pt[k].imag() < ret;
             n++) {
          ret = min(ret, abs(R[n] - pt[k]));
        }
      }
      inplace_merge(pt.begin() + j, pt.begin() + m,
                    j + i * 2 < pt.size() ? pt.begin() + j + 2 * i : pt.end(),
                    comp_y);
    }
  }
  return ret;
}

P centerofgravity(const vector<P> &pt) {
  P ret(0, 0);
  D wt = 0;
  for (int i = 2; i < pt.size(); i++) {
    D w2 = cross(pt[i - 1] - pt[0], pt[i] - pt[0]);
    P p = (pt[0] + pt[i - 1] + pt[i]) / (D)3;
    wt += w2;
    ret += p * w2;
  }
  return ret / wt;
}

void segment_arrangement(const vector<pair<P, P>> &L,
                         vector<pair<int, int>> &seg, vector<P> &pt) {
  int N = (int)L.size();
  for (int i = 0; i < N; i++) {
    pt.push_back(L[i].F);
    pt.push_back(L[i].S);
    for (int j = i + 1; j < N; j++) {
      if (intersectSS(L[i].F, L[i].S, L[j].F, L[j].S)) {
        pt.push_back(crosspointSS(L[i].F, L[i].S, L[j].F, L[j].S));
      }
    }
  }
  auto le = [](P a, P b) { return eqls(a, b) ? false : comp(a, b); };
  sort(pt.begin(), pt.end(), le);
  pt.erase(unique(pt.begin(), pt.end(), eqls), pt.end());
  for (auto &I : L) {
    vector<pair<D, int>> on;
    for (int j = 0; j < (int)pt.size(); j++) {
      if (distSP(I.F, I.S, pt[j]) < EPS) {
        on.emplace_back(abs(pt[j] - I.F), j);
      }
    }
    sort(on.begin(), on.end());
    for (int j = 1; j < (int)on.size(); j++) {
      seg.emplace_back(on[j - 1].S, on[j].S);
    }
  }
  sort(seg.begin(), seg.end());
  seg.erase(unique(seg.begin(), seg.end()), seg.end());
}

vector<P> convex_of_segments(const vector<pair<P, P>> &L) {
  vector<pair<int, int>> seg;
  vector<P> pt;
  segment_arrangement(L, seg, pt);
  vector<vector<int>> edge(pt.size());
  for (auto &I : seg) {
    edge[I.F].push_back(I.S);
    edge[I.S].push_back(I.F);
  }
  vector<P> ret;
  function<void(int, int)> dfs = [&](int v, int pre) {
    if (pre != -1 && v == 0) {
      return;
    }
    ret.push_back(pt[v]);
    vector<pair<D, int>> nx;
    for (auto &u : edge[v]) {
      D a = arg((pt[u] - pt[v]) /
                (pre == -1 || eqls(pt[v], pt[pre]) ? P(1) : pt[v] - pt[pre]));
      if (abs(a + PI) < EPS) {
        a = PI;
      }
      nx.emplace_back(a, u);
    }
    sort(nx.begin(), nx.end());
    dfs(nx[0].S, v);
  };
  dfs(0, -1);
  return ret;
}

istream &operator>>(istream &i, P &p) {
  D x, y;
  i >> x >> y;
  p = {x, y};
  return i;
}
istream &operator>>(istream &i, C &p) {
  D x, y;
  i >> x >> y >> p.S;
  p.F = {x, y};
  return i;
}
}; // namespace Geometry

using namespace Geometry;

int main() {
  ll n;
  cin >> n;
  vector<P> A(n);
  cin >> A;
  vector<pair<P, P>> B(n - 1);
  for (int j = 1; j < n; j++) {
    B[j - 1] = {A[j - 1], A[j]};
  }
  cout << fixed << setprecision(12) << area(convex_of_segments(B)) << endl;

  return 0;
}


Error: WA

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pi;
typedef pair<double, double> pd;
typedef pair<double, ll> pdl;
#define F first
#define S second
const ll E = 1e18 + 7;
const ll MOD = 1000000007;

// BEGIN CUT HERE

#define double long double
#define EPS (1e-8)
#define equals(a, b) (fabs((a) - (b)) < EPS)
#define PI 3.141592653589793238

// COUNTER CLOCKWISE
static const int CCW_COUNTER_CLOCKWISE = 1;
static const int CCW_CLOCKWISE = -1;
static const int CCW_ONLINE_BACK = 2;
static const int CCW_ONLINE_FRONT = -2;
static const int CCW_ON_SEGMENT = 0;

// Intercsect Circle & Circle
static const int ICC_SEPERATE = 4;
static const int ICC_CIRCUMSCRIBE = 3;
static const int ICC_INTERSECT = 2;
static const int ICC_INSCRIBE = 1;
static const int ICC_CONTAIN = 0;

struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point operator+(Point p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point p) { return Point(x - p.x, y - p.y); }
  Point operator*(double k) { return Point(x * k, y * k); }
  Point operator/(double k) { return Point(x / k, y / k); }
  double norm() { return x * x + y * y; }
  double abs() { return sqrt(norm()); }

  bool operator<(const Point &p) const {
    if (p == *this) {
      return false;
    }
    return x != p.x ? x < p.x : y < p.y;
    // grid-point only
    // return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0;
  }

  bool operator==(const Point &p) const {
    return fabs(x - p.x) / 100 < EPS && fabs(y - p.y) / 100 < EPS;
  }
};

struct EndPoint {
  Point p;
  int seg, st;
  EndPoint() {}
  EndPoint(Point p, int seg, int st) : p(p), seg(seg), st(st) {}
  bool operator<(const EndPoint &ep) const {
    if (p.y == ep.p.y)
      return st < ep.st;
    return p.y < ep.p.y;
  }
};

istream &operator>>(istream &is, Point &p) {
  is >> p.x >> p.y;
  return is;
}

ostream &operator<<(ostream &os, Point p) {
  os << fixed << setprecision(12) << p.x << " " << p.y;
  return os;
}

bool sort_x(Point a, Point b) { return a.x != b.x ? a.x < b.x : a.y < b.y; }

bool sort_y(Point a, Point b) { return a.y != b.y ? a.y < b.y : a.x < b.x; }

typedef Point Vector;
typedef vector<Point> Polygon;

istream &operator>>(istream &is, Polygon &p) {
  for (int i = 0; i < (int)p.size(); i++)
    is >> p[i];
  return is;
}

struct Segment {
  Point p1, p2;
  Segment() {}
  Segment(Point p1, Point p2) : p1(p1), p2(p2) {}
};
typedef Segment Line;

istream &operator>>(istream &is, Segment &s) {
  is >> s.p1 >> s.p2;
  return is;
}

struct Circle {
  Point c;
  double r;
  Circle() {}
  Circle(Point c, double r) : c(c), r(r) {}
};

istream &operator>>(istream &is, Circle &c) {
  is >> c.c >> c.r;
  return is;
}

double norm(Vector a) { return a.x * a.x + a.y * a.y; }
double abs(Vector a) { return sqrt(norm(a)); }
double dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }
double cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }

Point orth(Point p) { return Point(-p.y, p.x); }

bool isOrthogonal(Vector a, Vector b) { return equals(dot(a, b), 0.0); }

bool isOrthogonal(Point a1, Point a2, Point b1, Point b2) {
  return isOrthogonal(a1 - a2, b1 - b2);
}

bool isOrthogonal(Segment s1, Segment s2) {
  return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

bool isParallel(Vector a, Vector b) { return equals(cross(a, b), 0.0); }

bool isParallel(Point a1, Point a2, Point b1, Point b2) {
  return isParallel(a1 - a2, b1 - b2);
}

bool isParallel(Segment s1, Segment s2) {
  return equals(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

Point project(Segment s, Point p) {
  Vector base = s.p2 - s.p1;
  double r = dot(p - s.p1, base) / norm(base);
  return s.p1 + base * r;
}

Point reflect(Segment s, Point p) { return p + (project(s, p) - p) * 2.0; }

double arg(Vector p) { return atan2(p.y, p.x); }

Vector polar(double a, double r) { return Point(cos(r) * a, sin(r) * a); }

int ccw(Point p0, Point p1, Point p2);
bool intersectSS(Point p1, Point p2, Point p3, Point p4);
bool intersectSS(Segment s1, Segment s2);
bool intersectPS(Polygon p, Segment l);
int intersectCC(Circle c1, Circle c2);
bool intersectSC(Segment s, Circle c);
double getDistanceLP(Line l, Point p);
double getDistanceSP(Segment s, Point p);
double getDistanceSS(Segment s1, Segment s2);
Point getCrossPointSS(Segment s1, Segment s2);
Point getCrossPointLL(Line l1, Line l2);
Polygon getCrossPointCL(Circle c, Line l);
Polygon getCrossPointCC(Circle c1, Circle c2);
int contains(Polygon g, Point p);
Polygon andrewScan(Polygon s);
Polygon convex_hull(Polygon ps);
double diameter(Polygon s);
bool isConvex(Polygon p);
double area(Polygon s);
Polygon convexCut(Polygon p, Line l);
Line bisector(Point p1, Point p2);
Vector translate(Vector v, double theta);
vector<Line> corner(Line l1, Line l2);
vector<vector<pair<int, double>>> segmentArrangement(vector<Segment> &ss,
                                                     Polygon &ps);

int ccw(Point p0, Point p1, Point p2) {
  Vector a = p1 - p0;
  Vector b = p2 - p0;
  if (cross(a, b) > EPS)
    return CCW_COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CCW_CLOCKWISE;
  if (dot(a, b) < -EPS)
    return CCW_ONLINE_BACK;
  if (a.norm() < b.norm())
    return CCW_ONLINE_FRONT;
  return CCW_ON_SEGMENT;
}

bool intersectSS(Point p1, Point p2, Point p3, Point p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}

bool intersectSS(Segment s1, Segment s2) {
  return intersectSS(s1.p1, s1.p2, s2.p1, s2.p2);
}

bool intersectPS(Polygon p, Segment l) {
  int n = p.size();
  for (int i = 0; i < n; i++)
    if (intersectSS(Segment(p[i], p[(i + 1) % n]), l))
      return 1;
  return 0;
}

int intersectCC(Circle c1, Circle c2) {
  if (c1.r < c2.r)
    swap(c1, c2);
  double d = abs(c1.c - c2.c);
  double r = c1.r + c2.r;
  if (equals(d, r))
    return ICC_CIRCUMSCRIBE;
  if (d > r)
    return ICC_SEPERATE;
  if (equals(d + c2.r, c1.r))
    return ICC_INSCRIBE;
  if (d + c2.r < c1.r)
    return ICC_CONTAIN;
  return ICC_INTERSECT;
}

bool intersectSC(Segment s, Circle c) { return getDistanceSP(s, c.c) <= c.r; }

int intersectCS(Circle c, Segment s) {
  if (norm(project(s, c.c) - c.c) - c.r * c.r > EPS)
    return 0;
  double d1 = abs(c.c - s.p1), d2 = abs(c.c - s.p2);
  if (d1 < c.r + EPS && d2 < c.r + EPS)
    return 0;
  if ((d1 < c.r - EPS && d2 > c.r + EPS) || (d1 > c.r + EPS && d2 < c.r - EPS))
    return 1;
  Point h = project(s, c.c);
  if (dot(s.p1 - h, s.p2 - h) < 0)
    return 2;
  return 0;
}

double getDistanceLP(Line l, Point p) {
  return abs(cross(l.p2 - l.p1, p - l.p1) / abs(l.p2 - l.p1));
}

double getDistanceSP(Segment s, Point p) {
  if (dot(s.p2 - s.p1, p - s.p1) < 0.0)
    return abs(p - s.p1);
  if (dot(s.p1 - s.p2, p - s.p2) < 0.0)
    return abs(p - s.p2);
  return getDistanceLP(s, p);
}

double getDistanceSS(Segment s1, Segment s2) {
  if (intersectSS(s1, s2))
    return 0.0;
  return min(min(getDistanceSP(s1, s2.p1), getDistanceSP(s1, s2.p2)),
             min(getDistanceSP(s2, s1.p1), getDistanceSP(s2, s1.p2)));
}

Point getCrossPointSS(Segment s1, Segment s2) {
  for (int k = 0; k < 2; k++) {
    if (getDistanceSP(s1, s2.p1) < EPS)
      return s2.p1;
    if (getDistanceSP(s1, s2.p2) < EPS)
      return s2.p2;
    swap(s1, s2);
  }
  Vector base = s2.p2 - s2.p1;
  double d1 = abs(cross(base, s1.p1 - s2.p1));
  double d2 = abs(cross(base, s1.p2 - s2.p1));
  double t = d1 / (d1 + d2);
  return s1.p1 + (s1.p2 - s1.p1) * t;
}

Point getCrossPointLL(Line l1, Line l2) {
  double a = cross(l1.p2 - l1.p1, l2.p2 - l2.p1);
  double b = cross(l1.p2 - l1.p1, l1.p2 - l2.p1);
  if (abs(a) < EPS && abs(b) < EPS)
    return l2.p1;
  return l2.p1 + (l2.p2 - l2.p1) * (b / a);
}

Polygon getCrossPointCL(Circle c, Line l) {
  Polygon ps;
  Point pr = project(l, c.c);
  Vector e = (l.p2 - l.p1) / abs(l.p2 - l.p1);
  if (equals(getDistanceLP(l, c.c), c.r)) {
    ps.emplace_back(pr);
    return ps;
  }
  double base = sqrt(c.r * c.r - norm(pr - c.c));
  ps.emplace_back(pr + e * base);
  ps.emplace_back(pr - e * base);
  return ps;
}

Polygon getCrossPointCS(Circle c, Segment s) {
  Line l(s);
  Polygon res = getCrossPointCL(c, l);
  if (intersectCS(c, s) == 2)
    return res;
  if (res.size() > 1u) {
    if (dot(l.p1 - res[0], l.p2 - res[0]) > 0)
      swap(res[0], res[1]);
    res.pop_back();
  }
  return res;
}

Polygon getCrossPointCC(Circle c1, Circle c2) {
  Polygon p(2);
  double d = abs(c1.c - c2.c);
  double a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
  double t = arg(c2.c - c1.c);
  p[0] = c1.c + polar(c1.r, t + a);
  p[1] = c1.c + polar(c1.r, t - a);
  return p;
}

// IN:2 ON:1 OUT:0
int contains(Polygon g, Point p) {
  int n = g.size();
  bool x = false;
  for (int i = 0; i < n; i++) {
    Point a = g[i] - p, b = g[(i + 1) % n] - p;
    if (fabs(cross(a, b)) < EPS && dot(a, b) < EPS)
      return 1;
    if (a.y > b.y)
      swap(a, b);
    if (a.y < EPS && EPS < b.y && cross(a, b) > EPS)
      x = !x;
  }
  return (x ? 2 : 0);
}

Polygon andrewScan(Polygon s) {
  Polygon u, l;
  if (s.size() < 3)
    return s;
  sort(s.begin(), s.end());
  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size() - 1]);
  l.push_back(s[s.size() - 2]);
  for (int i = 2; i < (int)s.size(); i++) {
    for (int n = u.size();
         n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) != CCW_CLOCKWISE; n--) {
      u.pop_back();
    }
    u.push_back(s[i]);
  }
  for (int i = s.size() - 3; i >= 0; i--) {
    for (int n = l.size();
         n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) != CCW_CLOCKWISE; n--) {
      l.pop_back();
    }
    l.push_back(s[i]);
  }
  reverse(l.begin(), l.end());
  for (int i = u.size() - 2; i >= 1; i--)
    l.push_back(u[i]);
  return l;
}

Polygon convex_hull(Polygon ps) {
  int n = ps.size();
  sort(ps.begin(), ps.end(), sort_y);
  int k = 0;
  Polygon qs(n * 2);
  for (int i = 0; i < n; i++) {
    while (k > 1 && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < 0)
      k--;
    qs[k++] = ps[i];
  }
  for (int i = n - 2, t = k; i >= 0; i--) {
    while (k > t && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < 0)
      k--;
    qs[k++] = ps[i];
  }
  qs.resize(k - 1);
  return qs;
}

double diameter(Polygon s) {
  Polygon p = s;
  int n = p.size();
  if (n == 2)
    return abs(p[0] - p[1]);
  int i = 0, j = 0;
  for (int k = 0; k < n; k++) {
    if (p[i] < p[k])
      i = k;
    if (!(p[j] < p[k]))
      j = k;
  }
  double res = 0;
  int si = i, sj = j;
  while (i != sj || j != si) {
    res = max(res, abs(p[i] - p[j]));
    if (cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) < 0.0) {
      i = (i + 1) % n;
    } else {
      j = (j + 1) % n;
    }
  }
  return res;
}

bool isConvex(Polygon p) {
  bool f = 1;
  int n = p.size();
  for (int i = 0; i < n; i++) {
    int t = ccw(p[(i + n - 1) % n], p[i], p[(i + 1) % n]);
    f &= t != CCW_CLOCKWISE;
  }
  return f;
}

double area(Polygon s) {
  double res = 0;
  for (int i = 0; i < (int)s.size(); i++) {
    res += cross(s[i], s[(i + 1) % s.size()]) / 2.0;
  }
  return abs(res);
}

double area(Circle c1, Circle c2) {
  double d = abs(c1.c - c2.c);
  if (c1.r + c2.r <= d + EPS)
    return 0;
  if (d <= abs(c1.r - c2.r)) {
    double r = min(c1.r, c2.r);
    return PI * r * r;
  }
  double rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  double th = acos(rc / c1.r);
  double ph = acos((d - rc) / c2.r);
  return c1.r * c1.r * th + c2.r * c2.r * ph - d * c1.r * sin(th);
}

Polygon convexCut(Polygon p, Line l) {
  Polygon q;
  for (int i = 0; i < (int)p.size(); i++) {
    Point a = p[i], b = p[(i + 1) % p.size()];
    if (ccw(l.p1, l.p2, a) != -1)
      q.push_back(a);
    if (ccw(l.p1, l.p2, a) * ccw(l.p1, l.p2, b) < 0)
      q.push_back(getCrossPointLL(Line(a, b), l));
  }
  return q;
}

Line bisector(Point p1, Point p2) {
  Circle c1 = Circle(p1, abs(p1 - p2)), c2 = Circle(p2, abs(p1 - p2));
  Polygon p = getCrossPointCC(c1, c2);
  if (cross(p2 - p1, p[0] - p1) > 0)
    swap(p[0], p[1]);
  return Line(p[0], p[1]);
}

Vector translate(Vector v, double theta) {
  Vector res;
  res.x = cos(theta) * v.x - sin(theta) * v.y;
  res.y = sin(theta) * v.x + cos(theta) * v.y;
  return res;
}

vector<Line> corner(Line l1, Line l2) {
  vector<Line> res;
  if (isParallel(l1, l2)) {
    double d = getDistanceLP(l1, l2.p1) / 2.0;
    Vector v1 = l1.p2 - l1.p1;
    v1 = v1 / v1.abs() * d;
    Point p = l2.p1 + translate(v1, 90.0 * (PI / 180.0));
    double d1 = getDistanceLP(l1, p);
    double d2 = getDistanceLP(l2, p);
    if (abs(d1 - d2) > d) {
      p = l2.p1 + translate(v1, -90.0 * (PI / 180.0));
    }
    res.push_back(Line(p, p + v1));
  } else {
    Point p = getCrossPointLL(l1, l2);
    Vector v1 = l1.p2 - l1.p1, v2 = l2.p2 - l2.p1;
    v1 = v1 / v1.abs();
    v2 = v2 / v2.abs();
    res.push_back(Line(p, p + (v1 + v2)));
    res.push_back(Line(p, p + translate(v1 + v2, 90.0 * (PI / 180.0))));
  }
  return res;
}

Polygon tangent(Circle c1, Point p2) {
  Circle c2 = Circle(p2, sqrt(norm(c1.c - p2) - c1.r * c1.r));
  Polygon p = getCrossPointCC(c1, c2);
  sort(p.begin(), p.end());
  return p;
}

vector<Line> tangent(Circle c1, Circle c2) {
  vector<Line> ls;
  if (c1.r < c2.r)
    swap(c1, c2);
  double g = norm(c1.c - c2.c);
  if (equals(g, 0))
    return ls;
  Point u = (c2.c - c1.c) / sqrt(g);
  Point v = orth(u);
  for (int s = 1; s >= -1; s -= 2) {
    double h = (c1.r + s * c2.r) / sqrt(g);
    if (equals(1 - h * h, 0)) {
      ls.emplace_back(c1.c + u * c1.r, c1.c + (u + v) * c1.r);
    } else if (1 - h * h > 0) {
      Point uu = u * h, vv = v * sqrt(1 - h * h);
      ls.emplace_back(c1.c + (uu + vv) * c1.r, c2.c - (uu + vv) * c2.r * s);
      ls.emplace_back(c1.c + (uu - vv) * c1.r, c2.c - (uu - vv) * c2.r * s);
    }
  }

  return ls;
}

double closest_pair(Polygon &a, int l = 0, int r = -1) {
  if (r < 0) {
    r = a.size();
    sort(a.begin(), a.end(), sort_x);
  }
  if (r - l <= 1)
    return abs(a[0] - a[1]);
  int m = (l + r) >> 1;
  double x = a[m].x;
  double d = min(closest_pair(a, l, m), closest_pair(a, m, r));
  inplace_merge(a.begin() + l, a.begin() + m, a.begin() + r, sort_y);

  Polygon b;
  for (int i = l; i < r; i++) {
    if (fabs(a[i].x - x) >= d)
      continue;
    for (int j = 0; j < (int)b.size(); j++) {
      double dy = a[i].y - next(b.rbegin(), j)->y;
      if (dy >= d)
        break;
      d = min(d, abs(a[i] - *next(b.rbegin(), j)));
    }
    b.emplace_back(a[i]);
  }
  return d;
}

vector<vector<pair<int, double>>> segmentArrangement(vector<Segment> &ss,
                                                     Polygon &ps) {
  int n = ss.size();
  for (int i = 0; i < n; i++) {
    ps.emplace_back(ss[i].p1);
    ps.emplace_back(ss[i].p2);
    for (int j = i + 1; j < n; j++)
      if (intersectSS(ss[i], ss[j]))
        ps.emplace_back(getCrossPointSS(ss[i], ss[j]));
  }
  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());

  vector<vector<pair<int, double>>> G(ps.size());
  for (int i = 0; i < n; i++) {
    vector<pair<double, int>> ls;
    for (int j = 0; j < (int)ps.size(); j++)
      if (getDistanceSP(ss[i], ps[j]) < EPS)
        ls.emplace_back(make_pair(norm(ss[i].p1 - ps[j]), j));

    sort(ls.begin(), ls.end());
    for (int j = 0; j + 1 < (int)ls.size(); j++) {
      int a = ls[j].second, b = ls[j + 1].second;
      G[a].emplace_back(b, abs(ps[a] - ps[b]));
      G[b].emplace_back(a, abs(ps[a] - ps[b]));
    }
  }
  return G;
}

int manhattanIntersection(vector<Segment> ss, const int INF) {
  const int BTM = 0;
  const int LFT = 1;
  const int RGH = 2;
  const int TOP = 3;

  int n = ss.size();
  vector<EndPoint> ep;
  for (int i = 0; i < n; i++) {
    if (ss[i].p1.y == ss[i].p2.y) {
      if (ss[i].p1.x > ss[i].p2.x)
        swap(ss[i].p1, ss[i].p2);
      ep.emplace_back(ss[i].p1, i, LFT);
      ep.emplace_back(ss[i].p2, i, RGH);
    } else {
      if (ss[i].p1.y > ss[i].p2.y)
        swap(ss[i].p1, ss[i].p2);
      ep.emplace_back(ss[i].p1, i, BTM);
      ep.emplace_back(ss[i].p2, i, TOP);
    }
  }
  sort(ep.begin(), ep.end());

  set<int> bt;
  bt.insert(INF);

  int cnt = 0;
  for (int i = 0; i < n * 2; i++) {
    if (ep[i].st == TOP) {
      bt.erase(ep[i].p.x);
    } else if (ep[i].st == BTM) {
      bt.emplace(ep[i].p.x);
    } else if (ep[i].st == LFT) {
      auto b = bt.lower_bound(ss[ep[i].seg].p1.x);
      auto e = bt.upper_bound(ss[ep[i].seg].p2.x);
      cnt += distance(b, e);
    }
  }

  return cnt;
}

double area(Polygon ps, Circle c) {
  if (ps.size() < 3u)
    return 0;
  function<double(Circle, Point, Point)> dfs = [&](Circle c, Point a, Point b) {
    Vector va = c.c - a, vb = c.c - b;
    double f = cross(va, vb), res = 0;
    if (equals(f, 0.0))
      return res;
    if (max(abs(va), abs(vb)) < c.r + EPS)
      return f;
    Vector d(dot(va, vb), cross(va, vb));
    if (getDistanceSP(Segment(a, b), c.c) > c.r - EPS)
      return c.r * c.r * atan2(d.y, d.x);
    auto u = getCrossPointCS(c, Segment(a, b));
    if (u.empty())
      return res;
    if (u.size() > 1u && dot(u[1] - u[0], a - u[0]) > 0)
      swap(u[0], u[1]);
    u.emplace(u.begin(), a);
    u.emplace_back(b);
    for (int i = 1; i < (int)u.size(); i++)
      res += dfs(c, u[i - 1], u[i]);
    return res;
  };
  double res = 0;
  for (int i = 0; i < (int)ps.size(); i++)
    res += dfs(c, ps[i], ps[(i + 1) % ps.size()]);
  return res / 2;
}

// END CUT HERE

struct LowLink {
  set<pair<int, int>> bridge;
  vector<int> articulation, ord, low;
  vector<bool> used;
  vector<vector<int>> g;
  int n, k = 0;
  LowLink(const vector<vector<int>> &g) : g(g) {
    n = g.size();
    ord.resize(n, 0);
    low.resize(n, 0);
    used.resize(n, false);
  }
  void dfs(int u, int prev) {
    used[u] = true;
    ord[u] = k++;
    low[u] = ord[u];
    bool is_articulation = false;
    int cnt = 0;
    for (auto v : g[u])
      if (v != prev) {
        if (!used[v]) {
          cnt++;
          dfs(v, u);
          low[u] = min(low[u], low[v]);
          if (low[v] > ord[u]) {
            bridge.emplace(min(u, v), max(u, v));
          }
          if (prev != -1 && low[v] >= ord[u]) {
            is_articulation = true;
          }
        } else {
          low[u] = min(low[u], ord[v]);
        }
      }
    if (prev == -1 && cnt > 1)
      is_articulation = true;
    if (is_articulation)
      articulation.push_back(u);
  }
};
struct TwoEdgeConnectedComponent {
  int n;
  vector<vector<int>> g, tree;
  vector<int> cmp;
  TwoEdgeConnectedComponent(const vector<vector<int>> &g) : g(g) {
    n = (int)g.size();
    cmp.assign(n, -1);
  }
  int build() {
    LowLink lnk(g);
    lnk.dfs(0, -1);
    int k = 0;
    function<void(int, int)> dfs = [&](int u, int prev) {
      cmp[u] = k;
      for (auto v : g[u])
        if (cmp[v] == -1 && lnk.bridge.count({min(u, v), max(u, v)}) == 0) {
          dfs(v, u);
        }
    };
    for (int i = 0; i < n; i++)
      if (cmp[i] == -1) {
        dfs(i, -1);
        k++;
      }
    tree.resize(k);
    for (auto e : lnk.bridge) {
      tree[cmp[e.first]].push_back(cmp[e.second]);
      tree[cmp[e.second]].push_back(cmp[e.first]);
    }
    return k;
  }
};

typedef complex<double> C;

C toC(Point A) { return C(A.x, A.y); }

map<Point, ll> M;
map<ll, Point> R;
set<pll> Edge;

int main() {
  ll n;
  cin >> n;
  vector<Point> A(n);
  ll num = 0;
  for (auto &I : A) {
    cin >> I;
    if (M.count(I) == 0) {
      M[I] = num;
      R[num] = I;
      num++;
    }
  }
  for (int i = 1; i < n; i++) {
    set<Point> S;
    S.insert(A[i]);
    S.insert(A[i - 1]);
    for (int t = 1; t < n; t++) {
      if (i == t) {
        continue;
      }
      if (i < t) {
        if (intersectSS(A[i - 1], A[i], A[t - 1], A[t])) {
          S.insert(getCrossPointLL({A[i - 1], A[i]}, {A[t - 1], A[t]}));
        }
      } else {
        if (intersectSS(A[t - 1], A[t], A[i - 1], A[i])) {
          S.insert(getCrossPointLL({A[t - 1], A[t]}, {A[i - 1], A[i]}));
        }
      }
    }
    ll l = -1;
    for (auto I = S.begin(); I != S.end(); ++I) {
      if (M.count(*I) == 0) {
        M[*I] = num;
        R[num] = *I;
        num++;
      }
      if (l == -1) {
        l = M[*I];
      } else {
        Edge.insert({l, M[*I]});
        Edge.insert({M[*I], l});
        l = M[*I];
      }
    }
  }

  // for(auto I=R.begin();I!=R.end();++I){cout<<I->first<<" "<<I->second<<endl;}

  vector<vector<int>> G(num);
  for (auto I = Edge.begin(); I != Edge.end(); ++I) {
    // cout<<I->first<<" "<<I->second<<endl;
    G[I->first].push_back((int)(I->second));
  }
  TwoEdgeConnectedComponent T(G);
  int K = T.build();

  double ret = 0;

  for (int i = 0; i < K; i++) {
    // cout<<i<<" "<<K<<endl;

    vector<Point> A;
    for (int t = 0; t < num; t++) {
      if (T.cmp[t] == i) {
        A.push_back(R[t]);
      }
    }
    if (A.size() > 2) {
      sort(A.begin(), A.end(),
           [](Point p, Point q) { return p.y == q.y ? p.x < q.x : p.y < q.y; });
      Point pre = A[0];
      ll npre = M[A[0]];
      Point nx = A[0];
      for (auto &I : G[npre]) {
        if (nx == pre) {
          if (T.cmp[I] == T.cmp[npre]) {
            nx = R[I];
          }
        } else if (T.cmp[I] == T.cmp[npre] && arg(R[I] - pre) < arg(nx - pre)) {
          nx = R[I];
        }
      }
      if (nx == pre) {
        assert(false);
      }
      double ans = 0;

      set<pll> used;

      // for(auto &I:A){cout<<I<<endl;}
      // cout<<endl;

      function<void(ll, ll, ll)> dfs = [&](ll w, ll pre, ll root) {
        // if(used.count({w,pre})){return;}
        // used.insert({w,pre});
        // cout<<w<<" "<<pre<<" "<<root<<endl;
        ans += cross(R[w] - R[root], R[pre] - R[root]);
        if (w == root) {
          return;
        }
        ll nx = -1;
        for (auto &I : G[w]) {
          if (T.cmp[I] != T.cmp[w] || I == pre) {
            continue;
          }
          if (nx == -1) {
            nx = I;
          } else if (arg(toC(R[I] - R[pre]) / toC(R[w] - R[pre])) <
                     arg(toC(R[nx] - R[pre]) / toC(R[w] - R[pre]))) {
            nx = I;
          }
        }
        if (nx == -1) {
          assert(false);
        }
        dfs(nx, w, root);
      };

      // cout<<pre<<" "<<nx<<endl;
      dfs(M[nx], M[pre], M[pre]);
      // cout<<abs(ans)<<endl;
      ret += abs(ans);
    }
  }
  ret /= 2;
  cout << fixed << setprecision(12) << ret << endl;

  return 0;
}