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<iostream>
#include<cmath>
#include<complex>
#include<vector>
#include<set>
#include<cassert>
#include<algorithm>
#include<iomanip>

using namespace std;

typedef long double elem;
typedef complex<elem> point, vec;
typedef pair<point,point> seg, line;

const elem eps = 1e-8;
const elem pi = 2*acos(0.0);

enum CCW{ccw_f=0x01,ccw_r=0x02,ccw_b=0x04,ccw_l=0x08,ccw_o=0x10};

struct edge{
  int src,dst;
  elem cost;
  edge(int src, int dst, elem cost):src(src),dst(dst),cost(cost){}
};

typedef vector<edge> edges;
typedef vector<edges> graph;

bool eq(elem a, elem b){ return abs(b-a)<eps; }
bool leq(elem a, elem b){ return eq(a,b) || a<b; }
bool ls(elem a, elem b){ return !eq(a,b) && a<b; }
elem dot(const point &a, const point &b){ return a.real()*b.real()+a.imag()*b.imag(); }
elem cross(const point &a, const point &b){ return (a.real()*b.imag()-a.imag()*b.real()); }

int ccw(const point &a, point b, point c){
  b-=a;
  c-=a;
  elem cr=cross(b,c);
  if(eq(cr,0)&&ls(dot(b,c),0))return ccw_b;
  if(eq(cr,0)&&ls(abs(b),abs(c)))return ccw_f;
  return eq(cr,0)?ccw_o:cr>0?ccw_l:ccw_r;
}

elem varg(const vec &a, const vec &b){
  assert(abs(a)>1e-7); // FAILED on Case 51
  assert(abs(b)>1e-7);

  elem ret=arg(a)-arg(b);
  if(ls(ret,0))ret+=2*pi;
  if(ls(2*pi,ret))ret-=2*pi;
  if(eq(ret,2*pi))ret=0;
  return ret;
}

elem dist_l(const line &l, const point &x){
  vec v = l.second - l.first;
  assert(!eq(abs(v),0));
  return abs(cross(v,x-l.first))/abs(v);
}

bool intersectedSS(const seg &s, const seg &t){
  point a0=s.first,a1=s.second,b0=t.first,b1=t.second;
  int a=ccw(a0,a1,b0),b=ccw(b0,b1,a0),c=ccw(a0,a1,b1),d=ccw(b0,b1,a1);

  //if(eq(abs(a0-b0),0)||eq(abs(a0-b1),0)||eq(abs(a1-b0),0)||eq(abs(a1-b1),0)) return false;
  // if((a|b|c|d)&ccw_o)return true;
  return (a|c)==(ccw_l|ccw_r)&&(b|d)==(ccw_l|ccw_r);
}

point intersectionSS(const seg &a, const seg &b){
  elem d1=dist_l(b,a.first);
  elem d2=dist_l(b,a.second);
  assert(!eq(d1+d2,0));
  return a.first+(d1/(d1+d2))*(a.second-a.first);
}

namespace std{
  bool operator<(const point &a, const point &b){
    if(!eq(a.real(),b.real()))return a.real()<b.real();
    if(!eq(a.imag(),b.imag()))return a.imag()<b.imag();
    return false;
  }  
}

struct di{
  elem d;
  int id;
  di(elem d, int id):d(d),id(id){}
  bool operator<(const di &t) const {
    if(!eq(d,t.d))return d < t.d;
    if(id!=t.id)return id < t.id;
    return false;
  }
};

graph segmentsArrangement(const vector<seg> &ss, vector<point> &ps){

  for(int i = 0; i < (int)ss.size(); ++i){
    ps.push_back(ss[i].first);
    ps.push_back(ss[i].second);
    for(int j = i+1; j < (int)ss.size(); ++j){
      if(intersectedSS(ss[i], ss[j])){
        ps.push_back(intersectionSS(ss[i],ss[j]));
      }
    }
  }

  for(int i = 0; i < (int)ps.size(); ++i){
    for(int j =i+1; j < (int)ps.size(); ++j){
      if( abs(ps[j]-ps[i])<1e-6 ){
        ps.erase( ps.begin() + j );
        j = i;
      }
    }
  }

  sort(ps.begin(),ps.end());
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  graph g(ps.size());
  for(int i = 0; i < (int)ss.size(); ++i){
    vector<di> list;
    for(int j = 0; j < (int)ps.size(); ++j){
      if(ccw(ss[i].first,ss[i].second,ps[j])==ccw_o)
        list.push_back(di(abs(ss[i].first-ps[j]),j));
    }

    sort(list.begin(),list.end());
    for(int j = 0; j+1 < (int)list.size(); ++j){
      int a = list[j].id, b = list[j+1].id;
      g[a].push_back(edge(a,b,abs(ps[a]-ps[b])));
      g[b].push_back(edge(b,a,abs(ps[b]-ps[a])));
    }
  }

  for(int i = 0; i < (int)g.size(); ++i){
    for(int j = 0; j < (int)g[i].size(); ++j){
      for(int k = 1+j; k < (int)g[i].size(); ++k){
        if(g[i][j].dst == g[i][k].dst){
          g[i].erase(g[i].begin()+k);
          k = j;
        }
      }
    }
  }

  return g;
}

bool overlappedSegment(const seg &a, const seg &b){
  if(ccw(a.first,a.second,b.first)==ccw_o&&ccw(a.first,a.second,b.second)==ccw_o)return true;
  if(ccw(b.first,b.second,a.first)==ccw_o&&ccw(b.first,b.second,a.second)==ccw_o)return true;
  return false;
}

void removeOverlappedSegments(vector<seg> &s){
  for(int i = 0; i < (int)s.size(); ++i){
    for(int j = i+1; j < (int)s.size(); ++j){
      if(overlappedSegment(s[i],s[j])){
        s.erase(s.begin()+j);
        j = i;
      }
    }
  }
}

elem areaOfPolygon(const vector<point> &vp){
  elem ret = 0;
  for(int i = 0; i < (int)vp.size(); ++i){
    ret += cross(vp[i], vp[(i+1)%vp.size()]);
  }
  return abs(ret/2.);
}

vector<point> disolveArrangement(const graph &g, const vector<point> &ps){

  int start = -1;
  double minY = 1000000;
  for(int i = 0; i < (int)ps.size(); ++i){
    if( ls( ps[i].imag(), minY ) ){
      minY = ps[i].imag();
      start = i;
    }
  }

  vector<int> path;
  vector<point> ret;

  int prev = -1;
  int cur = start;
  int org_prev = -1;
  int org_cur;

  path.push_back(cur);
  do{
    int cand = -1;
    double maxArg = -4*pi;
    vector<di> v;
    
    // cout << prev << ' ' << cur << endl;
    for(int i = 0; i < (int)g[cur].size(); ++i){
      edge e = g[cur][i];
      point pre;
      if( prev != -1 ){
        pre = ps[prev];
      }else{
        pre = ps[cur] - point(0,3);
      }
      v.push_back(di(varg(pre-ps[cur],ps[e.dst]-ps[cur]),e.dst));
    }

    for(int i = 0; i < (int)v.size(); ++i){
      if( ls(maxArg, v[i].d ) ){
        maxArg=v[i].d;
        cand=v[i].id;
      }
    }

    prev = cur;
    cur = cand;
    
    if( org_prev == -1 ){
      org_prev = prev;
      org_cur = cur;
    }else if( cur == org_cur && prev == org_prev ){
      break;
    }
    
    path.push_back(cur);
  }while( true );

  for(int i = 0; i < (int)path.size(); ++i){
    ret.push_back( ps[path[i]] );
  }

  return ret;
}

int main()
{
  int N;
  while(cin >> N){
    vector<seg> e;
    vector<point> ps;
    elem preX = 1000000;
    elem preY = 1000000;
    
    for(int i = 0; i < N; ++i){
      elem X,Y;
      cin >> X >> Y;
      assert(-100000<=X && X<=100000);
      assert(-100000<=Y && Y<=100000);
      assert(!eq(preX,X)||!eq(preY,Y));
      if(i>0){
        e.push_back(seg(point(preX,preY),point(X,Y)));
      }
      preX = X;
      preY = Y;
    }

    removeOverlappedSegments(e);
    graph g = segmentsArrangement(e, ps);

    /*
    cout << setprecision(3) << "Arranged : " << endl;
    for(int i = 0; i < (int)g.size(); ++i){
      if(g[i].size()>0){
        cout << i << ps[g[i][0].src] << " : ";
        for(int j = 0; j < (int)g[i].size(); ++j){
          cout << g[i][j].dst << ps[g[i][j].dst] << ' ';
        }
        cout << endl;
      }
    }
    */
    
    vector<point> vv = disolveArrangement(g, ps);
    double S = areaOfPolygon(vv);

    cout << fixed << setprecision(12) << S << endl;
  }
  
  return 0;
}