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

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