#include <bits/stdc++.h>
using namespace std;
#define prev jfwekljfwekl
typedef complex<double> P;
typedef vector<P> G;
const double EPS = 1e-9;
namespace std {
	bool operator < (const P& a, const P& b) {
		if( abs(a-b) < EPS ) return false;
		return fabs(real(a)-real(b)) < EPS ? imag(a) < imag(b) : real(a) < real(b);
	} 
}
double cross(P a,P b) { return imag(conj(a)*b); }
double dot(P a,P b) { return real(conj(a)*b);}

//??´???
struct L : public vector<P> {
	L(P a,P b) {
		push_back(a); push_back(b);
	}
	
};

int ccw(P a, P b, P c) {
	b -= a; c -= a;
	if (cross(b, c) > 0)   return +1;	// a ??? b ??§???????¨??????????????????? b ??? c(???)
	if (cross(b, c) < 0)   return -1;	// a ??? b ??§????¨??????????????????? b ??? c(???)
	if (dot(b, c) < 0) return +2;    	// a???b??§????????????a??????????¶???????b???c(c--a--b)
	if (norm(b) < norm(c)) return -2;	// a???b??§????????????b???c(a--b--c)
	return 0;							// a???b??§????????????b???c(????????? b == c)
}

bool intersectSS(const L &s, const L &t) {	// <= 0??? < ???????????¨???????????¨?????????????????????
	return	ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 && 
			ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}

P crosspoint(const L &l, const L &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0];
	return m[0] + B / A * (m[1] - m[0]);
}

bool intersectSP(const L &s, const P &p) {
	return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS;
}

double area2(const G& poly) {
	double A = 0;
	for(int i = 0 ; i < poly.size() ; i++)
		A += cross(poly[i], poly[(i+1)%poly.size()]);
	return abs(A);
}

map<P,set<P>> graph;

vector<P> poly;

double myatan2(P p){
	return atan2(p.imag(),p.real());
}

double dfs(P init,P prev, P cur){
	if( abs(init-cur) < EPS ){
		return area2(poly) / 2.0;
	}
	vector< pair<double,P> > ps;
	for(auto p : graph[cur] ){
		ps.push_back({myatan2(p-cur),p});
		ps.push_back({myatan2(p-cur)+2*M_PI,p});
		ps.push_back({myatan2(p-cur)-2*M_PI,p});
	}
	
	sort(ps.begin(),ps.end());
	double target = myatan2(prev-cur);
	for(int i = 0 ; i < ps.size() ; i++){
		if( target + EPS < ps[i].first ){
			poly.push_back(cur);
			return dfs(init,cur,ps[i].second);
		}
	}
	assert(false);
	
	
}
int main(){
	int n;
	cin >> n;
	G g;
	
	set<P> ps;
	for(int i = 0 ; i < n ; i++){
		int x,y;
		cin >> x >> y;
		g.push_back(P(x,y));
		ps.insert(P(x,y));
		
	}
	
	vector<L> cand;
	auto addp = [&](P a,P b){
		if( abs(a-b) > EPS ){
			graph[a].insert(b);
			graph[b].insert(a);
		}
	};
	
	for(int i = 0 ; i+1 < n ; i++){
		cand.push_back(L(g[i],g[i+1]));
		for(int j = i+1 ; j+1 < n ; j++){	
			auto l1 = L(g[i],g[i+1]);
			auto l2 = L(g[j],g[j+1]);
			if( intersectSS(l1,l2) ){
				auto cp = crosspoint(l1,l2);
				ps.insert(cp);
			}
		}
	}
	for( auto l : cand ){
		vector< pair<double,P> > ds;
		for( auto p : ps ){
			if( intersectSP(l,p) ){
				ds.push_back({abs(l[0]-p),p});
			}
		}
		sort(ds.begin(),ds.end());
		for(int j = 0 ; j+1 < ds.size() ; j++){
			addp(ds[j].second,ds[j+1].second);
		}
	}	
	
	queue<P> Q;
	for( auto v : graph ){
		if( v.second.size() <= 1 ){
			Q.push(v.first);
		}
	}
	map<P,bool> done;
	/*while( Q.size() ){
		auto q = Q.front(); Q.pop();
		for(auto v : graph[q] ){
			graph[v].erase(q);
			if( graph[v].size() <= 1 ){
				Q.push(v);
			}
		}
		graph.erase(q);
	}*/
	if( graph.size() == 0 ){
		puts("0.0");
	}else{	
		P sp = graph.begin()->first;
		vector<P> ip(graph.begin()->second.begin(),graph.begin()->second.end());
		sort(ip.begin(),ip.end(),[&](P a,P b){
			return cross(a-sp,b-sp) >= 0;
		});
		poly.push_back(sp);
		printf("%.10lf%c",dfs(sp,sp,ip[0]),10);
	}
	
	
	
}

Measured memory_bytes: 4608