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 <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

typedef long double R;
constexpr R EPS = 1e-8;

struct point {
	R x, y;
	explicit point(R x_ = 0.0, R y_ = 0.0):x(x_), y(y_) {}
	point(const point &p):x(p.x), y(p.y) {}

	point operator+(const point &p) const {
		return point(x + p.x, y + p.y);
	}

	point operator-(const point &p) const {
		return point(x - p.x, y - p.y);
	}

	point operator*(R s) const {
		return point(x * s, y * s);
	}

	point operator*(const point &p) const {
		return point(x * p.x - y * p.y, x * p.y + y * p.x);
	}

	point operator/(R s) const {
		return point(x / s, y / s);
	}

	bool operator<(const point &p) const {
		return x + EPS < p.x || (abs(x - p.x) < EPS && y + EPS < p.y);
	}

	bool operator==(const point &p) const {
		return abs(x - p.x) < EPS && abs(y - p.y) < EPS;
	}
};

R angle(const point &p) {
	return atan2(p.y, p.x);
}

R norm(const point &p) {
	return p.x * p.x + p.y * p.y;
}

R abs(const point &p) {
	return sqrt(norm(p));
}

R dot(const point &a, const point &b) {
	return a.x * b.x + a.y * b.y;
}

R cross(const point &a, const point &b) {
	return a.x * b.y - a.y * b.x;
}

struct segment {
	point a, b;
	segment(const point &a_, const point &b_):a(a_), b(b_){}
};

typedef vector<point> polygon;

int ccw(const point &a, point b, point c) {
	b = b - a;
	c = c - a;
	const R tmp = cross(b, c);
	if(tmp > EPS) return 1; // ccw
	if(tmp < -EPS) return -1; // cw
	if(dot(b, c) < 0) return 2; // c, a, b 順に一直線上
	if(norm(b) < norm(c)) return -2; // a, b, c 順に一直線上
	return 0; //a, c, b 順で一直線上
}

bool intersect(const segment &s, const segment &t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0
		&& ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool intersect(const segment &s, const point &p) {
	return ccw(s.a, s.b, p) == 0;
}

// 先にintersectで交差判定をすること
point crosspoint(const segment &s, const segment &t) {
	const R tmp = cross(s.b - s.a, t.b - t.a);
	if(abs(tmp) < EPS) { // 一直線上
		if(intersect(s, t.a)) return t.a;
		if(intersect(s, t.b)) return t.b;
		if(intersect(t, s.a)) return s.a;
		return s.b;
	}
	return t.a + (t.b - t.a) * (cross(s.b - s.a, s.b - t.a) / tmp);
}

R area(const polygon &P) {
	const int n = P.size();
	if(n < 3) return 0;

	R res = 0.0;
	point prev = P.back();

	for(const auto &curr : P) {
		res += cross(prev, curr);
		prev = curr;
	}
	return res * 0.5;
}

struct edge {
	int to;
	R theta;
	bool used;

	edge(int to_, R theta_):to(to_), theta(theta_), used(false) {}

	inline bool operator<(const edge &e) const {
		return theta < e.theta;
	}
};

typedef vector<vector<edge>> graph;

graph arrangement(const vector<segment> &segments, vector<point> &points) {
	const int n = segments.size();
	points.clear();

	for(int i = 0; i < n; ++i) {
		const auto &s1 = segments[i];
		points.emplace_back(s1.a);
		points.emplace_back(s1.b);

		for(int j = i + 1; j < n; ++j) {
			const auto &s2 = segments[j];
			if(intersect(s1, s2)) {
				points.emplace_back(crosspoint(s1, s2));
			}
		}
	}

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

	const int V = points.size();
	graph G(V);

	for(const auto &s : segments) {
		vector<pair<R, int>> vs;
		for(int i = 0; i < V; ++i) {
			if(intersect(s, points[i])) {
				vs.emplace_back(abs(s.a - points[i]), i);
			}
		}

		sort(vs.begin(), vs.end());
		for(int i = 1; i < static_cast<int>(vs.size()); ++i) {
			const int v = vs[i].second;
			const int u = vs[i - 1].second;
			G[v].emplace_back(u, angle(points[u] - points[v]));
			G[u].emplace_back(v, angle(points[v] - points[u]));
		}
	}

	for(auto &edges : G) sort(begin(edges), end(edges));
	return G;
}

void merge(vector<segment> &segments) {
	for(int i = 0; i < static_cast<int>(segments.size());) {
		const auto &s1 = segments[i];
		bool ok = true;
		for(int j = i + 1; j < static_cast<int>(segments.size()); ++j) {
			const auto &s2 = segments[j];

			if(intersect(s1, s2) && abs(cross(s1.a - s1.b, s2.a - s2.b)) < EPS) {
				const auto a = min(min(s1.a, s1.b), min(s2.a, s2.b));
				const auto b = max(max(s1.a, s1.b), max(s2.a, s2.b));
				segments.emplace_back(a, b);

				segments.erase(segments.begin() + j);
				segments.erase(segments.begin() + i);
				ok = false;
				break;
			}
		}
		if(ok) ++i;
	}
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(10);

	int n;
	cin >> n;

	point prev;
	vector<segment> segments;
	segments.reserve(n - 1);

	for(int i = 0; i < n; ++i) {
		int x, y;
		cin >> x >> y;

		const point curr(x, y);
		if(i) segments.emplace_back(prev, curr);
		prev = move(curr);
	}

	vector<point> points;
	merge(segments);
	auto G = arrangement(segments, points);

	const int V = G.size();

	R ans = 0.0;
	for(int i = 0; i < V; ++i) {
		for(int j = 0; j < static_cast<int>(G[i].size()); ++j) {
			int v = i;
			int e_idx = j;
			polygon P;

			while(true) {
				edge &e = G[v][e_idx];
				if(e.used) break;

				e.used = true;
				P.emplace_back(points[v]);

				for(int k = 0; k < static_cast<int>(G[e.to].size()); ++k) {
					if(G[e.to][k].to == v) {
						v = e.to;
						e_idx = (k + 1) % G[e.to].size();
						break;
					}
				}
			}

			const R tmp = area(P);
			if(tmp < EPS) ans -= tmp;
		}
	}

	cout << ans << endl;

	return EXIT_SUCCESS;
}