Problem: You are given one polygonal line, which is a collection of line segments. Your task is to calculate the sum of areas enclosed by the polygonal line.

A point is defined to be "enclosed" if and only if the point is unreachable without crossing at least one line segment from the point at infinity.



Input

The first line contains one integers N (2 ≤ N ≤ 100). N is the number of segments.

Each of the following N lines consists of two integers Xi and Yi (-105 ≤ Xi, Yi ≤ 105, 1 ≤ i ≤ N) which represents a vertex. A polygonal line is the segments which connect (Xj, Yj) and (Xj+1, Yj+1) ((Xj, Yj) ≠ (Xj+1, Yj+1), 1 ≤ j ≤ N-1). The distance between a segment Sj and all vertices except the end points on segment Sj is guaranteed to be greater than 0.01.

Output

Output the answer in a line. The answer may be printed with an arbitrary number of decimal digits, but may not contain an absolute or relative error greater than or equal to 10-6.

Examples

Input

5
0 0
1 1
1 0
0 1
0 0


Output

0.5


Input

5
0 0
1 1
1 0
0 1
1 0


Output

0.25


Input

21
1 1
-1 1
-1 2
-2 2
-2 1
-1 1
-1 -1
-2 -1
-2 -2
-1 -2
-1 -1
1 -1
1 -2
2 -2
2 -1
1 -1
1 1
2 1
2 2
1 2
1 1


Output

8


Input

16
0 0
1 0
1 1
0 1
0 2
0 3
1 3
1 2
2 2
2 3
3 3
3 2
3 1
2 1
2 0
3 0


Output

0


Input

7
26 52
33 12
-51 68
16 61
43 -26
87 24
12 10


Output

2714.840579710

Solution (in CPP):

Solution:
#include<bits/stdc++.h>

using namespace std;

const double EPS = 1e-5, PI = acos(-1), INF = 1e9;

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

struct Point
{
  double x, y;

  Point() {};

  Point(double x, double y) : x(x), y(y) {};

  Point operator+(const Point &b) const { return Point(x + b.x, y + b.y); }

  Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); }

  Point operator*(const double b) const { return Point(x * b, y * b); }

  Point operator*(const Point &b) const { return Point(x * b.x - y * b.y, x * b.y + y * b.x); }

  Point operator/(const double b) const { return Point(x / b, y / b); }

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

  bool operator==(const Point &b) const { return eq(x, b.x) && eq(y, b.y); }

  double norm() const { return x * x + y * y; }

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

  double abs() const { return sqrt(norm()); }

  Point rotate(double theta) { return Point(cos(theta) * x - sin(theta) * y, sin(theta) * x + cos(theta) * y); }

  Point rotate90() { return Point(-y, x); }

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

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


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, Point b, Point c)
{
  b = b - a, c = c - a;
  if(cross(b, c) > EPS) return +1;
  if(cross(b, c) < -EPS) return -1;
  if(dot(b, c) < 0) return +2;
  if(b.norm() < c.norm()) return -2;
  return 0;
}

struct Segment
{
  Point a, b;

  Segment() {};

  Segment(Point a, Point b) : a(a), b(b) {};

  friend ostream &operator<<(ostream &os, Segment &p) { return os << "(" << p.a.x << "," << p.a.y << ") to (" << p.b.x << "," << p.b.y << ")"; }

  friend istream &operator>>(istream &is, Segment &a) { return is >> a.a.x >> a.a.y >> a.b.x >> a.b.y; }
};

typedef vector< Point > Polygon;

double Area2(const Polygon &p)
{
  double A = 0;
  for(int i = 0; i < p.size(); ++i) {
    A += cross(p[i], p[(i + 1) % p.size()]);
  }
  return A;
}

bool Intersect(const Segment &s, const Point &p)
{
  return ccw(s.a, s.b, p) == 0;
}

bool Intersect(const Segment &s, const Segment &t)
{
  return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
         ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

Point Crosspoint(const Segment &l, const Segment &m)
{
  double A = cross(l.b - l.a, m.b - m.a);
  double B = cross(l.b - l.a, l.b - m.a);
  if(abs(A) < EPS && abs(B) < EPS) return m.a; // same line
  return m.a + (m.b - m.a) * B / A;
}

double GetAngle(const Point &a, const Point &b)
{
  double tmp = min(1.0, max(-1.0, dot(a, b) / a.abs() / b.abs()));
  double r = acos(tmp) * 180.0 / PI;
  if(cross(a, b) < -EPS) r = 360 - r;
  return r;
}

bool merge_if_able(Segment &s1, Segment s2)
{
  if(abs(cross(s1.b - s1.a, s2.b - s2.a)) > EPS) return false;
  if(ccw(s1.a, s2.a, s1.b) == 1 ||
     ccw(s1.a, s2.a, s1.b) == -1)
    return false;
  if(ccw(s1.a, s1.b, s2.a) == -2 ||
     ccw(s2.a, s2.b, s1.a) == -2)
    return false;
  s1 = Segment(min(s1.a, s2.a), max(s1.b, s2.b));
  return true;
}

void merge_segments(vector< Segment > &segs)
{
  for(int i = 0; i < segs.size(); i++) {
    if(segs[i].b < segs[i].a) swap(segs[i].a, segs[i].b);
  }
  for(int i = 0; i < segs.size(); i++) {
    for(int j = i + 1; j < segs.size(); j++) {
      if(merge_if_able(segs[i], segs[j])) {
        segs[j--] = segs.back(), segs.pop_back();
      }
    }
  }
}

vector< vector< int > > SegmentArrangement(vector< Segment > &segs, vector< Point > &ps)
{
  vector< vector< int > > g;
  const int N = (int) segs.size();
  for(int i = 0; i < N; i++) {
    ps.emplace_back(segs[i].a);
    ps.emplace_back(segs[i].b);
    for(int j = i + 1; j < N; j++) {
      const Point p1 = segs[i].b - segs[i].a;
      const Point p2 = segs[j].b - segs[j].a;
      if(cross(p1, p2) == 0) continue;
      if(Intersect(segs[i], segs[j])) {
        ps.emplace_back(Crosspoint(segs[i], segs[j]));
      }
    }
  }
  sort(begin(ps), end(ps));
  ps.erase(unique(begin(ps), end(ps)), end(ps));

  const int M = (int) ps.size();
  g.resize(M);
  for(int i = 0; i < N; i++) {
    vector< int > vec;
    for(int j = 0; j < M; j++) {
      if(Intersect(segs[i], ps[j])) {
        vec.emplace_back(j);
      }
    }
    for(int j = 1; j < vec.size(); j++) {
      g[vec[j - 1]].push_back(vec[j]);
      g[vec[j]].push_back(vec[j - 1]);
    }
  }
  return (g);
}

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

  int N;
  cin >> N;
  vector< Segment > segs;

  {
    Point pv;
    for(int i = 0; i < N; i++) {
      Point curr;
      cin >> curr;
      if(i) segs.emplace_back((Segment) {pv, curr});
      pv = curr;
    }
  }

  vector< Point > ps;
  merge_segments(segs);
  auto g = SegmentArrangement(segs, ps);

  Point s(INF, INF);
  int t;
  for(auto &p : ps) s = min(s, p);
  for(int i = 0; i < ps.size(); i++) if(ps[i] == s) t = i;

  Polygon poly;

  function< void(int, int) > dfs = [&](int idx, int par)
  {
    if(idx == t) return;
    pair< double, int > nxt(INF, -1);
    for(auto &to : g[idx]) {
      double arg = GetAngle(ps[par] - ps[idx], ps[to] - ps[idx]);
      if(to == par) arg = 361;
      nxt = min(nxt, make_pair(arg, to));
    }
    poly.emplace_back(ps[idx]);
    dfs(nxt.second, idx);
  };
  double ret = 0;
  for(auto &to : g[t]) {
    poly.push_back(s);
    dfs(to, t);
    ret += max(0.0, Area2(poly));
    poly.clear();
  }
  cout << fixed << setprecision(12) << ret * 0.5 << endl;
}