// 
// 22 line ???????????????
//
#include <iostream>
#include <vector>
#include <cstdio>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <map>
#include <cassert>
#include <queue>
#include <set>
#include <functional>
#include <ctime>
#include <numeric>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x,a) { auto y=(x); if (sign(y-a)) { cout << "line " << __LINE__  << #x << " = " << y << " != " << a << endl; exit(-1); } }

#define dout if(0)cout

double urand() { return rand() / (1.0 + RAND_MAX); }

const double PI = acos(-1.0);

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
// notice: should be normalize to O(1)
const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS) return -1;
  if (x > +EPS) return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y; 
  point &operator+=(point p) { x += p.x; y += p.y; return *this; }
  point &operator*=(T a)     { x *= a;   y *= a;   return *this; }
  point &operator-=(point p) { x -= p.x; y -= p.y; return *this; }
  point &operator/=(T a)     { return *this *= (1.0/a); }
  point operator-() const    { return {-x, -y}; }
  bool operator<(point p) const { 
    if (sign(x - p.x)) return sign(x - p.x) < 0;
    return sign(y - p.y) < 0;
  }
};
bool operator>(point p, point q) { return q<p; }
bool operator<=(point p, point q) { return !(q<p); }
bool operator>=(point p, point q) { return !(p<q); }
bool operator==(point p, point q) { return !(p<q) && !(q<p); }
bool operator!=(point p, point q) { return (p<q) || !(q<p); }
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x*q.x+p.y*q.y; }
point::T cross(point p, point q) { return p.x*q.y-p.y*q.x; } // left turn > 0
point::T norm2(point p) { return dot(p,p); }
point orth(point p) { return {-p.y, p.x}; }
point::T norm(point p) { return sqrt(dot(p,p)); }

int sign_dot(point p, point q) {
  double a = norm(p), b = norm(q);
  if (sign(a) == 0 || sign(b) == 0) return 0;
  return sign(dot(p, q)/a/b);
}
int sign_cross(point p, point q) {
  double a = norm(p), b = norm(q);
  if (sign(a) == 0 || sign(b) == 0) return 0;
  return sign(cross(p, q)/a/b);
}

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

struct segment { point p, q; };

// s.p + A (s.q - s.p) == t.p + B (t.q - t.p)
// A (s.q - s.p) == t.p - s.p + B (t.q - t.p)
// A = (t.p - s.p)x(t.q - t.p)/(s.q - s.p)x(t.q - t.p)
//

vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p); 
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) { a = -a; b = -b; c = -c; }
  if (sign(b) < 0 || sign(a-b) < 0 ||
      sign(c) < 0 || sign(a-c) < 0) return {};      // disjoint
  if (sign(a) != 0) return {s.p + b/a*(s.q - s.p)}; // properly crossing
  vector<point> ps;                                 // same line
  auto insert_if_possible = [&](point p) {
    for (auto q: ps) if (sign(dot(p-q, p-q)) == 0) return;
    ps.push_back(p);
  };
  if (sign(dot(s.p-t.p, s.q-t.p)) <= 0) insert_if_possible(t.p);
  if (sign(dot(s.p-t.q, s.q-t.q)) <= 0) insert_if_possible(t.q);
  if (sign(dot(t.p-s.p, t.q-s.p)) <= 0) insert_if_possible(s.p);
  if (sign(dot(t.p-s.q, t.q-s.q)) <= 0) insert_if_possible(s.q);
  return ps;
}

/*
  struct Face {
    Edge *edge; // Any edge incident to this face (CCW)
    vector<point> ps; 
  };
*/

//
// Verified: AOJ1226
//
struct arrangement {
  // Doubly Connected Edge List, aka., DCEL
  struct Vertex; struct Edge;
  struct Vertex {
    point p;    // 
    Edge *edge; // any edge incident to this vertex
  };
  struct Edge { 
    Vertex *vertex;    // origin vertex of the edge
    Edge *twin;        // reverse edge of e
    Edge *prev, *next; // surrounding edges of face (CCW)
  };
  vector<Vertex*> vertices;
  vector<Edge*> edges;

  // Segments
  vector<segment> segs;

  // Sweep-Line Structure (RBST)
  struct node {
    int index;
    int size = 1;
    node *left = 0, *right = 0;
  } *root = 0;
  int size(node *x) { return x ? x->size : 0; }
  vector<node> ns;

  node *update(node *x) {
    if (x) x->size = 1 + size(x->left) + size(x->right);
    return x;
  }
  node *merge(node *x, node *y) {
    if (!x) return y;
    if (!y) return x;
    if (rand() % (x->size + y->size) < x->size) {
      x->right = merge(x->right, y);
      return update(x);
    } else {
      y->left = merge(x, y->left);
      return update(y);
    }
  }
  template <class C> // 3-way split: cond(x) < 0, cond(x) == 0, cond(x) > 0
  tuple<node*, node*, node*> split(node *x, C cond) {
    if (!x) return make_tuple(x,x,x);
    if (cond(x) == 0) {
      auto a = split(x->left, cond);
      auto b = split(x->right, cond);
      assert(get<2>(a) == 0);
      if (get<0>(b)) {
        cout << "error on processing " << x->index << endl;
        cout << get<0>(b) << " " << get<1>(b) << " " << get<2>(b) << endl;
      }
      assert(get<0>(b) == 0);
      x->left = x->right = 0; update(x);
      get<1>(a) = merge(merge(get<1>(a), x), get<1>(b));
      get<2>(a) = get<2>(b);
      return a;
    }
    if (cond(x) < 0) {
      auto a = split(x->right, cond);
      x->right = 0; update(x);
      get<0>(a) = merge(x, get<0>(a));
      return a;
    }
    if (cond(x) > 0) {
      auto a = split(x->left, cond);
      x->left = 0; update(x);
      get<2>(a) = merge(get<2>(a), x);
      return a;
    }
  }
  template <class F>
  void process(node *x, F func) {
    if (!x) return;
    process(x->left, func);
    func(x);
    process(x->right, func);
  }
  node *leftmost(node *x) { 
    while (x && x->left) x = x->left;
    return x;
  }
  node *rightmost(node *x) {
    while (x && x->right) x = x->right;
    return x;
  }

  set<point> events;
  void display(node *x, int tab = 0) {
    if (!x) return;
    const point &p = *events.begin();
    display(x->left, tab+2);

    auto cond = [&](node *x) {
      const segment &s = segs[x->index];
      //assert(sign(s.p.x - p.x) <= 0);
      //assert(sign(s.q.x - p.x) >= 0);
      if (sign(s.q.x - s.p.x) == 0) {
        if (sign(p.y - s.p.y) < 0) return -1;
        if (sign(s.q.y - p.y) < 0) return +1;
        return 0;
      }
      return -sign_cross(s.p - p, s.q - p);
    };

    dout << string(tab, ' ') << x->index << " (" << segs[x->index].p << "," << segs[x->index].q << ") " << cond(x) << endl;
    display(x->right, tab+2);
  }

  // merge overlapping segments?
  void preprocess() {
    for (int i = 0; i < segs.size(); ++i) {
      if (segs[i].q < segs[i].p) swap(segs[i].p, segs[i].q);
    }
  }
  // ??? uniqueness ?????????????????§?????? uniqueness ??§???
  arrangement(vector<segment> segs_) : segs(segs_) {
    preprocess();
    ns.resize(segs.size());
    map<point, set<int>> L, R;

    for (int i = 0; i < segs.size(); ++i) {
      dout << i << ": " << segs[i].p << " " << segs[i].q << endl;
    }

    //map<Vertex*, vector<Edge*>> inc;
    map<Vertex*, map<Vertex*, Edge*>> adj;

    for (int i = 0; i < segs.size(); ++i) {
      events.insert(segs[i].p);
      events.insert(segs[i].q);
      L[segs[i].p].insert(i);
      R[segs[i].q].insert(i);
      ns[i].index = i;
    }
    vector<Vertex*> last(segs.size());

    while (!events.empty()) {
      const point p = *events.begin();
      Vertex *u = new Vertex({p});
      vertices.push_back(u);

      dout << "processing " << p << endl;
      display(root);
      events.erase(events.begin());
      
      auto cond = [&](node *x) {
        const segment &s = segs[x->index];
        assert(sign(s.p.x - p.x) <= 0);
        assert(sign(s.q.x - p.x) >= 0);
        if (sign(s.q.x - s.p.x) == 0) {
          dout << "  horizontal segment " << x->index << " is: ";
          if (sign(p.y - s.p.y) < 0) dout << "-1" << endl;
          if (sign(s.q.y - p.y) < 0) dout << "+1" << endl;
          if (sign(p.y - s.p.y) < 0) return -1;
          if (sign(s.q.y - p.y) < 0) return +1;
          dout << "0" << endl;
          return 0;
        }
        // cross ???????????????????????????
        // s.p + t (s.q - s.p) = p
        dout << "  segment " << x->index << " is: ";
        dout << -sign_cross(s.p - p, s.q - p) << endl;
        return -sign_cross(s.p - p, s.q - p);
      };
      auto z = split(root, cond);
      dout << "split: " << get<0>(z) << " " << get<1>(z) << " " << get<2>(z) << endl;
      vector<node*> inserter;
      dout << "segments on " << p << ":";
      process(get<1>(z), [&](node *x) {
        dout << " " << x->index;
        Vertex *v = last[x->index];
        assert(v != 0);
        if (!adj[u][v]) {
          adj[u][v] = new Edge({u});
          adj[v][u] = new Edge({v});
          adj[u][v]->twin = adj[v][u];
          adj[v][u]->twin = adj[u][v];
          edges.push_back(adj[u][v]);
          edges.push_back(adj[v][u]);
        }
        /*
        Edge *e = new Edge({u}), *r = new Edge({v});
        e->twin = r; r->twin = e;
        edges.push_back(e);
        edges.push_back(r);
        inc[u].push_back(e);
        inc[v].push_back(r);
        */
        if (!R[p].count(x->index)) 
          inserter.push_back(x);
      });
      dout << endl;
      for (int i: L[p]) {
        if (!R[p].count(i))
          inserter.push_back(&ns[i]);
      }
      sort(all(inserter), [&](node *x, node *y) {
        // x ??????????????????????°??????? ==> x -> y ??? ccw order
        // order at (p + epsilon) ??§?????????; 
        // we can assume that the segments contain p
        // ==> ??????????????§??????
        //
        const segment &s = segs[x->index], &t = segs[y->index];
        return sign_cross(s.q - s.p, t.q - t.p) >= 0;
      });
      auto add_event = [&](node *x, node *y) {
        if (!x || !y) return;
        dout << "add event, p = " << p << endl;
        vector<point> ps = intersect(segs[x->index], segs[y->index]);
        for (point q: ps) {
          dout << "crosspoint of " << x->index << " and " << y->index << " is " << q << endl;
          if (p < q) {
            dout << " ==> inserted" << endl;
            events.insert(q);
          } else {
            dout << " ==> ignored (" << p << " vs " << q << ") = " << (p < q) << endl;
          }
        }
        return;
      };
      if (inserter.empty()) {
        add_event(rightmost(get<0>(z)), leftmost(get<2>(z)));
      } else {
        add_event(rightmost(get<0>(z)), inserter[0]);
        add_event(leftmost(get<2>(z)), inserter.back());
      }
      root = 0;
      for (int i = 0; i < inserter.size(); ++i) {
        last[inserter[i]->index] = u;
        dout << "insert " << inserter[i]->index << endl;
        inserter[i]->left = inserter[i]->right = 0;
        root = merge(root, update(inserter[i]));
      }
      root = merge(merge(get<0>(z), root), get<2>(z));
    }
    for (auto &pp: adj) {
      Vertex *u = pp.fst;
      vector<Edge*> es;
      for (auto z: pp.snd) es.push_back(z.snd);
      sort(all(es), [&](Edge *e, Edge *f) {
        assert(e->vertex == f->vertex);
        auto quad = [](point p) {
          for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
            if (p.x > 0 && p.y >= 0) return i;
          return 0;
        };
        const point p = e->twin->vertex->p - e->vertex->p;
        const point q = f->twin->vertex->p - f->vertex->p;
        if (quad(p) != quad(q)) return quad(p) < quad(q);
        return sign_cross(p, q) > 0;
      });
      //cout << "vertex " << u->p << endl;
      u->edge = es.back();
      for (Edge *e: es) {
        //cout << "  edge " << e << ": " << e->vertex->p << " " << e->twin->vertex->p << "; " << e->twin << endl;
        u->edge->next = e;
        u->edge->next->prev = u->edge;
        u->edge = u->edge->next;
      }
    }

/*
    for (auto &pp: inc) {
      Vertex *u = pp.fst;
      vector<Edge*> &es = pp.snd;
      sort(all(inc[u]), [&](Edge *e, Edge *f) {
        assert(e->vertex == f->vertex);
        auto quad = [](point p) {
          for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
            if (p.x > 0 && p.y >= 0) return i;
          return 0;
        };
        const point p = e->twin->vertex->p - e->vertex->p;
        const point q = f->twin->vertex->p - f->vertex->p;
        if (quad(p) != quad(q)) return quad(p) < quad(q);
        if (sign(cross(p, q))) return sign(cross(p, q)) > 0;
        return cross(p, q) > 0;
      });
      cout << "vertex " << u->p << endl;
      u->edge = es.back();
      for (Edge *e: es) {
        cout << "  edge " << e << ": " << e->vertex->p << " " << e->twin->vertex->p << "; " << e->twin << endl;
        u->edge->next = e;
        u->edge->next->prev = u->edge;
        u->edge = u->edge->next;
      }
    }
    */
  }
};

void AOJ1226() {
  for (int n; ~scanf("%d", &n) && n; ) {
    //cout << n << endl;
    vector<vector<double>> a(4, vector<double>(n));
    for (int k = 0; k < 4; ++k)
      for (int i = 0; i < n; ++i)
        scanf("%lf", &a[k][i]);

    vector<segment> ss = {
      {{0,0},{0,1}},
      {{0,1},{1,1}},
      {{1,1},{1,0}},
      {{1,0},{0,0}}
    };
    for (int i = 0; i < n; ++i) {
      ss.push_back({{a[0][i],0},{a[1][i],1}});
      ss.push_back({{0,a[2][i]},{1,a[3][i]}});
    }
    arrangement arr(ss);

    double result = 0;
    set<arrangement::Edge*> seen;
    for (auto *e: arr.edges) {
      if (seen.count(e)) continue;
      auto *f = e;
      double area = 0;
      do {
        seen.insert(f);
        area += cross(f->vertex->p, f->twin->vertex->p);
        f = f->twin->prev;
      } while (f != e);
      result = max(result, area);
    }
    printf("%.6f\n", result/2);
  }
}
// 
// s.p + a (s.q - s.p) == t.p + b (t.q - t.p)
// ????§£?????????????????????????????\?????°????????? a ???????????? a* ?????????
//

void AOJ2448() {
  int n; scanf("%d", &n);
  vector<point> ps(n);
  for (int i = 0; i < n; ++i)
    scanf("%lf %lf", &ps[i].x, &ps[i].y);
  vector<segment> ss;
  for (int i = 0; i+1 < n; ++i)
    ss.push_back({ps[i], ps[i+1]});
  arrangement arr(ss);

  double result = 0;
  set<arrangement::Edge*> seen;
  for (auto *e: arr.edges) {
    if (seen.count(e)) continue;
    auto *f = e;
    double area = 0;
    do {
      seen.insert(f);
      area += cross(f->vertex->p, f->twin->vertex->p);
      f = f->twin->prev;
    } while (f != e);
    if (area > 0) result += area;
  }
  printf("%.12f\n", result/2);
}

int main() {
  //AOJ1226();
  AOJ2448();
  return 0;
  /*
  for (int seed =0; seed < 10000; ++seed) {
    cout << "seed = " << seed << endl;
    srand(seed);
    int n = 100;
    vector<segment> ss;
    int x = 0, y = 0;
    for (int i = 0; i < n; ++i) {
      int z = rand() % n, w = rand() % n;
      ss.push_back({{x,y},{z,w}});
      x = z; y = w;
      //cout << ss.back().p << " " << ss.back().q << endl;
    }
    arrangement arr(ss);
  }
  */
  /*
  ss.push_back({{0,0},{3,2}});
  ss.push_back({{0,1},{3,1}});
  ss.push_back({{2,0},{2,4}});
  //ss.push_back({{0,3},{3,2}});
  //ss.push_back({{1.5,0},{1.5,4}});
  //
  */

  /*
  auto *v = arr.get({1,1});
  auto *e = v->edge;
  do { 
    cout << e->vertex->p << " -- " << e->twin->vertex->p << endl;
    e = e->next;
  } while (e != v->edge);
  */
}
### Prompt

Please formulate a Cpp solution to the following 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

### Response

```cpp
// 
// 22 line ???????????????
//
#include <iostream>
#include <vector>
#include <cstdio>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <map>
#include <cassert>
#include <queue>
#include <set>
#include <functional>
#include <ctime>
#include <numeric>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x,a) { auto y=(x); if (sign(y-a)) { cout << "line " << __LINE__  << #x << " = " << y << " != " << a << endl; exit(-1); } }

#define dout if(0)cout

double urand() { return rand() / (1.0 + RAND_MAX); }

const double PI = acos(-1.0);

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
// notice: should be normalize to O(1)
const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS) return -1;
  if (x > +EPS) return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y; 
  point &operator+=(point p) { x += p.x; y += p.y; return *this; }
  point &operator*=(T a)     { x *= a;   y *= a;   return *this; }
  point &operator-=(point p) { x -= p.x; y -= p.y; return *this; }
  point &operator/=(T a)     { return *this *= (1.0/a); }
  point operator-() const    { return {-x, -y}; }
  bool operator<(point p) const { 
    if (sign(x - p.x)) return sign(x - p.x) < 0;
    return sign(y - p.y) < 0;
  }
};
bool operator>(point p, point q) { return q<p; }
bool operator<=(point p, point q) { return !(q<p); }
bool operator>=(point p, point q) { return !(p<q); }
bool operator==(point p, point q) { return !(p<q) && !(q<p); }
bool operator!=(point p, point q) { return (p<q) || !(q<p); }
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x*q.x+p.y*q.y; }
point::T cross(point p, point q) { return p.x*q.y-p.y*q.x; } // left turn > 0
point::T norm2(point p) { return dot(p,p); }
point orth(point p) { return {-p.y, p.x}; }
point::T norm(point p) { return sqrt(dot(p,p)); }

int sign_dot(point p, point q) {
  double a = norm(p), b = norm(q);
  if (sign(a) == 0 || sign(b) == 0) return 0;
  return sign(dot(p, q)/a/b);
}
int sign_cross(point p, point q) {
  double a = norm(p), b = norm(q);
  if (sign(a) == 0 || sign(b) == 0) return 0;
  return sign(cross(p, q)/a/b);
}

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

struct segment { point p, q; };

// s.p + A (s.q - s.p) == t.p + B (t.q - t.p)
// A (s.q - s.p) == t.p - s.p + B (t.q - t.p)
// A = (t.p - s.p)x(t.q - t.p)/(s.q - s.p)x(t.q - t.p)
//

vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p); 
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) { a = -a; b = -b; c = -c; }
  if (sign(b) < 0 || sign(a-b) < 0 ||
      sign(c) < 0 || sign(a-c) < 0) return {};      // disjoint
  if (sign(a) != 0) return {s.p + b/a*(s.q - s.p)}; // properly crossing
  vector<point> ps;                                 // same line
  auto insert_if_possible = [&](point p) {
    for (auto q: ps) if (sign(dot(p-q, p-q)) == 0) return;
    ps.push_back(p);
  };
  if (sign(dot(s.p-t.p, s.q-t.p)) <= 0) insert_if_possible(t.p);
  if (sign(dot(s.p-t.q, s.q-t.q)) <= 0) insert_if_possible(t.q);
  if (sign(dot(t.p-s.p, t.q-s.p)) <= 0) insert_if_possible(s.p);
  if (sign(dot(t.p-s.q, t.q-s.q)) <= 0) insert_if_possible(s.q);
  return ps;
}

/*
  struct Face {
    Edge *edge; // Any edge incident to this face (CCW)
    vector<point> ps; 
  };
*/

//
// Verified: AOJ1226
//
struct arrangement {
  // Doubly Connected Edge List, aka., DCEL
  struct Vertex; struct Edge;
  struct Vertex {
    point p;    // 
    Edge *edge; // any edge incident to this vertex
  };
  struct Edge { 
    Vertex *vertex;    // origin vertex of the edge
    Edge *twin;        // reverse edge of e
    Edge *prev, *next; // surrounding edges of face (CCW)
  };
  vector<Vertex*> vertices;
  vector<Edge*> edges;

  // Segments
  vector<segment> segs;

  // Sweep-Line Structure (RBST)
  struct node {
    int index;
    int size = 1;
    node *left = 0, *right = 0;
  } *root = 0;
  int size(node *x) { return x ? x->size : 0; }
  vector<node> ns;

  node *update(node *x) {
    if (x) x->size = 1 + size(x->left) + size(x->right);
    return x;
  }
  node *merge(node *x, node *y) {
    if (!x) return y;
    if (!y) return x;
    if (rand() % (x->size + y->size) < x->size) {
      x->right = merge(x->right, y);
      return update(x);
    } else {
      y->left = merge(x, y->left);
      return update(y);
    }
  }
  template <class C> // 3-way split: cond(x) < 0, cond(x) == 0, cond(x) > 0
  tuple<node*, node*, node*> split(node *x, C cond) {
    if (!x) return make_tuple(x,x,x);
    if (cond(x) == 0) {
      auto a = split(x->left, cond);
      auto b = split(x->right, cond);
      assert(get<2>(a) == 0);
      if (get<0>(b)) {
        cout << "error on processing " << x->index << endl;
        cout << get<0>(b) << " " << get<1>(b) << " " << get<2>(b) << endl;
      }
      assert(get<0>(b) == 0);
      x->left = x->right = 0; update(x);
      get<1>(a) = merge(merge(get<1>(a), x), get<1>(b));
      get<2>(a) = get<2>(b);
      return a;
    }
    if (cond(x) < 0) {
      auto a = split(x->right, cond);
      x->right = 0; update(x);
      get<0>(a) = merge(x, get<0>(a));
      return a;
    }
    if (cond(x) > 0) {
      auto a = split(x->left, cond);
      x->left = 0; update(x);
      get<2>(a) = merge(get<2>(a), x);
      return a;
    }
  }
  template <class F>
  void process(node *x, F func) {
    if (!x) return;
    process(x->left, func);
    func(x);
    process(x->right, func);
  }
  node *leftmost(node *x) { 
    while (x && x->left) x = x->left;
    return x;
  }
  node *rightmost(node *x) {
    while (x && x->right) x = x->right;
    return x;
  }

  set<point> events;
  void display(node *x, int tab = 0) {
    if (!x) return;
    const point &p = *events.begin();
    display(x->left, tab+2);

    auto cond = [&](node *x) {
      const segment &s = segs[x->index];
      //assert(sign(s.p.x - p.x) <= 0);
      //assert(sign(s.q.x - p.x) >= 0);
      if (sign(s.q.x - s.p.x) == 0) {
        if (sign(p.y - s.p.y) < 0) return -1;
        if (sign(s.q.y - p.y) < 0) return +1;
        return 0;
      }
      return -sign_cross(s.p - p, s.q - p);
    };

    dout << string(tab, ' ') << x->index << " (" << segs[x->index].p << "," << segs[x->index].q << ") " << cond(x) << endl;
    display(x->right, tab+2);
  }

  // merge overlapping segments?
  void preprocess() {
    for (int i = 0; i < segs.size(); ++i) {
      if (segs[i].q < segs[i].p) swap(segs[i].p, segs[i].q);
    }
  }
  // ??? uniqueness ?????????????????§?????? uniqueness ??§???
  arrangement(vector<segment> segs_) : segs(segs_) {
    preprocess();
    ns.resize(segs.size());
    map<point, set<int>> L, R;

    for (int i = 0; i < segs.size(); ++i) {
      dout << i << ": " << segs[i].p << " " << segs[i].q << endl;
    }

    //map<Vertex*, vector<Edge*>> inc;
    map<Vertex*, map<Vertex*, Edge*>> adj;

    for (int i = 0; i < segs.size(); ++i) {
      events.insert(segs[i].p);
      events.insert(segs[i].q);
      L[segs[i].p].insert(i);
      R[segs[i].q].insert(i);
      ns[i].index = i;
    }
    vector<Vertex*> last(segs.size());

    while (!events.empty()) {
      const point p = *events.begin();
      Vertex *u = new Vertex({p});
      vertices.push_back(u);

      dout << "processing " << p << endl;
      display(root);
      events.erase(events.begin());
      
      auto cond = [&](node *x) {
        const segment &s = segs[x->index];
        assert(sign(s.p.x - p.x) <= 0);
        assert(sign(s.q.x - p.x) >= 0);
        if (sign(s.q.x - s.p.x) == 0) {
          dout << "  horizontal segment " << x->index << " is: ";
          if (sign(p.y - s.p.y) < 0) dout << "-1" << endl;
          if (sign(s.q.y - p.y) < 0) dout << "+1" << endl;
          if (sign(p.y - s.p.y) < 0) return -1;
          if (sign(s.q.y - p.y) < 0) return +1;
          dout << "0" << endl;
          return 0;
        }
        // cross ???????????????????????????
        // s.p + t (s.q - s.p) = p
        dout << "  segment " << x->index << " is: ";
        dout << -sign_cross(s.p - p, s.q - p) << endl;
        return -sign_cross(s.p - p, s.q - p);
      };
      auto z = split(root, cond);
      dout << "split: " << get<0>(z) << " " << get<1>(z) << " " << get<2>(z) << endl;
      vector<node*> inserter;
      dout << "segments on " << p << ":";
      process(get<1>(z), [&](node *x) {
        dout << " " << x->index;
        Vertex *v = last[x->index];
        assert(v != 0);
        if (!adj[u][v]) {
          adj[u][v] = new Edge({u});
          adj[v][u] = new Edge({v});
          adj[u][v]->twin = adj[v][u];
          adj[v][u]->twin = adj[u][v];
          edges.push_back(adj[u][v]);
          edges.push_back(adj[v][u]);
        }
        /*
        Edge *e = new Edge({u}), *r = new Edge({v});
        e->twin = r; r->twin = e;
        edges.push_back(e);
        edges.push_back(r);
        inc[u].push_back(e);
        inc[v].push_back(r);
        */
        if (!R[p].count(x->index)) 
          inserter.push_back(x);
      });
      dout << endl;
      for (int i: L[p]) {
        if (!R[p].count(i))
          inserter.push_back(&ns[i]);
      }
      sort(all(inserter), [&](node *x, node *y) {
        // x ??????????????????????°??????? ==> x -> y ??? ccw order
        // order at (p + epsilon) ??§?????????; 
        // we can assume that the segments contain p
        // ==> ??????????????§??????
        //
        const segment &s = segs[x->index], &t = segs[y->index];
        return sign_cross(s.q - s.p, t.q - t.p) >= 0;
      });
      auto add_event = [&](node *x, node *y) {
        if (!x || !y) return;
        dout << "add event, p = " << p << endl;
        vector<point> ps = intersect(segs[x->index], segs[y->index]);
        for (point q: ps) {
          dout << "crosspoint of " << x->index << " and " << y->index << " is " << q << endl;
          if (p < q) {
            dout << " ==> inserted" << endl;
            events.insert(q);
          } else {
            dout << " ==> ignored (" << p << " vs " << q << ") = " << (p < q) << endl;
          }
        }
        return;
      };
      if (inserter.empty()) {
        add_event(rightmost(get<0>(z)), leftmost(get<2>(z)));
      } else {
        add_event(rightmost(get<0>(z)), inserter[0]);
        add_event(leftmost(get<2>(z)), inserter.back());
      }
      root = 0;
      for (int i = 0; i < inserter.size(); ++i) {
        last[inserter[i]->index] = u;
        dout << "insert " << inserter[i]->index << endl;
        inserter[i]->left = inserter[i]->right = 0;
        root = merge(root, update(inserter[i]));
      }
      root = merge(merge(get<0>(z), root), get<2>(z));
    }
    for (auto &pp: adj) {
      Vertex *u = pp.fst;
      vector<Edge*> es;
      for (auto z: pp.snd) es.push_back(z.snd);
      sort(all(es), [&](Edge *e, Edge *f) {
        assert(e->vertex == f->vertex);
        auto quad = [](point p) {
          for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
            if (p.x > 0 && p.y >= 0) return i;
          return 0;
        };
        const point p = e->twin->vertex->p - e->vertex->p;
        const point q = f->twin->vertex->p - f->vertex->p;
        if (quad(p) != quad(q)) return quad(p) < quad(q);
        return sign_cross(p, q) > 0;
      });
      //cout << "vertex " << u->p << endl;
      u->edge = es.back();
      for (Edge *e: es) {
        //cout << "  edge " << e << ": " << e->vertex->p << " " << e->twin->vertex->p << "; " << e->twin << endl;
        u->edge->next = e;
        u->edge->next->prev = u->edge;
        u->edge = u->edge->next;
      }
    }

/*
    for (auto &pp: inc) {
      Vertex *u = pp.fst;
      vector<Edge*> &es = pp.snd;
      sort(all(inc[u]), [&](Edge *e, Edge *f) {
        assert(e->vertex == f->vertex);
        auto quad = [](point p) {
          for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
            if (p.x > 0 && p.y >= 0) return i;
          return 0;
        };
        const point p = e->twin->vertex->p - e->vertex->p;
        const point q = f->twin->vertex->p - f->vertex->p;
        if (quad(p) != quad(q)) return quad(p) < quad(q);
        if (sign(cross(p, q))) return sign(cross(p, q)) > 0;
        return cross(p, q) > 0;
      });
      cout << "vertex " << u->p << endl;
      u->edge = es.back();
      for (Edge *e: es) {
        cout << "  edge " << e << ": " << e->vertex->p << " " << e->twin->vertex->p << "; " << e->twin << endl;
        u->edge->next = e;
        u->edge->next->prev = u->edge;
        u->edge = u->edge->next;
      }
    }
    */
  }
};

void AOJ1226() {
  for (int n; ~scanf("%d", &n) && n; ) {
    //cout << n << endl;
    vector<vector<double>> a(4, vector<double>(n));
    for (int k = 0; k < 4; ++k)
      for (int i = 0; i < n; ++i)
        scanf("%lf", &a[k][i]);

    vector<segment> ss = {
      {{0,0},{0,1}},
      {{0,1},{1,1}},
      {{1,1},{1,0}},
      {{1,0},{0,0}}
    };
    for (int i = 0; i < n; ++i) {
      ss.push_back({{a[0][i],0},{a[1][i],1}});
      ss.push_back({{0,a[2][i]},{1,a[3][i]}});
    }
    arrangement arr(ss);

    double result = 0;
    set<arrangement::Edge*> seen;
    for (auto *e: arr.edges) {
      if (seen.count(e)) continue;
      auto *f = e;
      double area = 0;
      do {
        seen.insert(f);
        area += cross(f->vertex->p, f->twin->vertex->p);
        f = f->twin->prev;
      } while (f != e);
      result = max(result, area);
    }
    printf("%.6f\n", result/2);
  }
}
// 
// s.p + a (s.q - s.p) == t.p + b (t.q - t.p)
// ????§£?????????????????????????????\?????°????????? a ???????????? a* ?????????
//

void AOJ2448() {
  int n; scanf("%d", &n);
  vector<point> ps(n);
  for (int i = 0; i < n; ++i)
    scanf("%lf %lf", &ps[i].x, &ps[i].y);
  vector<segment> ss;
  for (int i = 0; i+1 < n; ++i)
    ss.push_back({ps[i], ps[i+1]});
  arrangement arr(ss);

  double result = 0;
  set<arrangement::Edge*> seen;
  for (auto *e: arr.edges) {
    if (seen.count(e)) continue;
    auto *f = e;
    double area = 0;
    do {
      seen.insert(f);
      area += cross(f->vertex->p, f->twin->vertex->p);
      f = f->twin->prev;
    } while (f != e);
    if (area > 0) result += area;
  }
  printf("%.12f\n", result/2);
}

int main() {
  //AOJ1226();
  AOJ2448();
  return 0;
  /*
  for (int seed =0; seed < 10000; ++seed) {
    cout << "seed = " << seed << endl;
    srand(seed);
    int n = 100;
    vector<segment> ss;
    int x = 0, y = 0;
    for (int i = 0; i < n; ++i) {
      int z = rand() % n, w = rand() % n;
      ss.push_back({{x,y},{z,w}});
      x = z; y = w;
      //cout << ss.back().p << " " << ss.back().q << endl;
    }
    arrangement arr(ss);
  }
  */
  /*
  ss.push_back({{0,0},{3,2}});
  ss.push_back({{0,1},{3,1}});
  ss.push_back({{2,0},{2,4}});
  //ss.push_back({{0,3},{3,2}});
  //ss.push_back({{1.5,0},{1.5,4}});
  //
  */

  /*
  auto *v = arr.get({1,1});
  auto *e = v->edge;
  do { 
    cout << e->vertex->p << " -- " << e->twin->vertex->p << endl;
    e = e->next;
  } while (e != v->edge);
  */
}
```