#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;
}

Measured memory_bytes: 1892