#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <complex>
#include <algorithm>
#include <utility>
#include <numeric>
#include <cfloat>
#include <set>
#include <cstdlib>
#include <iomanip>
using namespace std;

typedef long double D;
typedef complex<D> P;
typedef pair<P,P> seg;

const D EPS = 1e-12;
const D INF = 1e99;

namespace std{
	bool operator< (const P &a, const P &b){
		if(abs(real(a) - real(b)) > EPS){
			return real(a) < real(b);
		}
		if(abs(imag(a) - imag(b)) > EPS){
			return imag(a) < imag(b);
		}
		return false;
	}
}

D dot(P a, P b){
	return real(a) * real(b) + imag(a) * imag(b);
}

D cross(P a, P b){
	return real(a) * imag(b) - imag(a) * real(b);
}

int ccw(P a, P b, P c){
	b -= a;
	c -= a;
	D cr = cross(b, c);
	D leps = abs(b) * abs(c) * EPS;
	if(abs(cr) > leps){
		return cr > 0.0 ? 1 : -1;
	}
	if(dot(b, c) < -leps){
		return 2;
	}
	if(abs(b) + EPS < abs(c)){
		return -2;
	}
	return 0;
}

int ccw(const seg &s, P c){
	return ccw(s.first, s.second, c);
}

P intrSS(P pa1, P pa2, P pb1, P pb2){
	P da12 = pa2 - pa1;
	P db21 = pb1 - pb2;
	P dab1 = pb1 - pa1;
	D d = cross(da12, db21);
	if(abs(d) > EPS){
		D t = cross(dab1, db21) / d;
		D s = cross(da12, dab1) / d;
		if(-EPS < t && t < 1.0 + EPS && -EPS < s && s < 1.0 + EPS){
			return pa1 + t * da12;
		}
	}
	return P(INF, INF);
}

P intrSS(const seg &s, const seg &t){
	return intrSS(s.first, s.second, t.first, t.second);
}


bool merge_if_able(seg &s, const seg &t){
	if(abs(cross(s.second - s.first, t.second - t.first)) > EPS){
		return false;
	}
	if(abs(ccw(s.first, t.first, s.second)) == 1){ return false; }
	if(ccw(s.first, s.second, t.first) == -2){ return false; }
	if(ccw(t.first, t.second, s.first) == -2){ return false; }
	s = seg(min(s.first, t.first), max(s.second, t.second));
	return true;
}
void merge_segments(vector<seg> &segs){
	for(int i = 0; i < segs.size(); ++i){
		if(segs[i].second < segs[i].first){
			swap(segs[i].second, segs[i].first);
		}
	}
	int inc = 1;
	for(int i = 0; i < segs.size(); i += inc){
		inc = 1;
		for(int j = i + 1; j < segs.size(); ++j){
			if(merge_if_able(segs[i], segs[j])){
				segs[j--] = segs.back();
				segs.pop_back();
				inc = 0;
			}
		}
	}
}


struct adjinfo{
	D angle;
	int anum;
	bool visit;

	explicit adjinfo(int a) : angle(0.0), anum(a), visit(false) {}
	
	bool operator< (const adjinfo &ai) const{
		return angle < ai.angle;
	}
};

vector<P> ps;
vector<vector<adjinfo> > G;

void segarrange(const vector<seg> &segs){
	set<P> s_ps;
	for(int i = 0; i < segs.size(); ++i){
		s_ps.insert(segs[i].first);
		s_ps.insert(segs[i].second);
		for(int j = i + 1; j < segs.size(); ++j){
			P ret = intrSS(segs[i], segs[j]);
			if(real(ret) < INF){
				s_ps.insert(ret);
			}
		}
	}

	ps.assign(s_ps.begin(), s_ps.end());

	G.clear();
	G.resize(ps.size());
	for(int i = 0; i < segs.size(); ++i){
		vector<pair<D,int> > ls;
		for(int j = 0; j < ps.size(); ++j){
			if(ccw(segs[i], ps[j]) == 0){
				ls.push_back(make_pair(abs(segs[i].first - ps[j]), j));
			}
		}
		sort(ls.begin(), ls.end());
		for(int j = 0; j + 1 < ls.size(); ++j){
			int a = ls[j].second, b = ls[j + 1].second;
			G[a].push_back(adjinfo(b));
			G[b].push_back(adjinfo(a));
		}
	}
}

D calcplg(int v, int k){
	P p0 = ps[v], p1 = ps[v];
	D ret = 0.0;
	while(1){
		G[v][k].visit = true;
		int w = G[v][k].anum;
		int nx;
		for(nx = 0; G[w][nx].anum != v; ++nx);
		if(--nx < 0){ nx += G[w].size(); }
		if(G[w][nx].visit){ break; }
		v = w;
		k = nx;

		P p2 = ps[v];
		ret += cross(p1 - p0, p2 - p0);
		p1 = p2;
	}
	return ret * 0.5;
}

int main(){
	int n;
	D x, y;
	cin >> n;

	vector<P> input(n);
	for(int i = 0; i < n; ++i){
		cin >> x >> y;
		input[i] = P(x, y);
	}
	
	vector<seg> segs(n - 1);
	for(int i = 0; i < n - 1; ++i){
		segs[i] = seg(input[i], input[i + 1]);
	}

	merge_segments(segs);

	segarrange(segs);

	for(int i = 0; i < ps.size(); ++i){
		for(int j = 0; j < G[i].size(); ++j){
			int to = G[i][j].anum;
			G[i][j].angle = arg(ps[to] - ps[i]);
		}
		sort(G[i].begin(), G[i].end());
	}

	D ans = 0.0;
	for(int i = 0; i < ps.size(); ++i){
		for(int j = 0; j < G[i].size(); ++j){
			if(!G[i][j].visit){
				D sq = calcplg(i, j);
				if(sq > 0.0){
					ans += sq;
				}
			}
		}
	}

	cout << fixed << setprecision(15) << ans << endl;
}

Measured memory_bytes: 2064