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 <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <utility>
#include <iostream>
#include <algorithm>
using namespace std;

struct Point {
	double x, y;

	Point(double x = 0.0, double y = 0.0) : x(x), y(y) {}

	Point& operator +=(const Point &o) { x += o.x, y += o.y; return *this; }
	Point& operator -=(const Point &o) { x -= o.x, y -= o.y; return *this; }
	Point& operator *=(double k) { x *= k, y *= k; return *this; }
	Point& operator /=(double k) { x /= k, y /= k; return *this; }

	bool on(const Point&, const Point&) const;

	double norm() const { return sqrt(x * x + y * y); }
	double arg() const { return atan2(y, x); }
};

Point operator +(Point a, const Point &b) { return a += b; }
Point operator -(Point a, const Point &b) { return a -= b; }
Point operator *(Point a, double k) { return a *= k; }
Point operator *(double k, Point a) { return a *= k; }
Point operator /(Point a, double k) { return a /= k; }

double det(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

const double EPS = 1e-8;

int signum(double x) { return x < -EPS ? -1 : x > EPS; }

bool Point::on(const Point &a, const Point &b) const {
	Point p = *this;
	double len = (a - p).norm();
	if (signum(len) == 0) return true;
	return signum(det(b - p, a - p) / len) == 0 && signum(dot(b - p, a - p)) <= 0;
}

Point intersect(const Point &a, const Point &b, const Point &c, const Point &d) {
	double s_1 = det(b - a, c - a);
	double s_2 = det(b - a, d - a);
	return (s_2 * c - s_1 * d) / (s_2 - s_1);
}

istream &operator >>(istream &in, Point &p) {
	return in >> p.x >> p.y;
}

bool operator==(const Point &a, const Point &b) { return signum(a.x - b.x) == 0 && signum(a.y - b.y) == 0; }
bool operator<(const Point &a, const Point &b) {
	if (signum(a.x - b.x) == 0) {
		return signum(a.y - b.y) < 0;
	}
	return signum(a.x - b.x) < 0;
}

const int N = 100;

int n;
Point End[N];
vector <Point> points;

const int V = N * N;
const int E = 6 * V;

int edgeCount, firstEdge[V], to[E], nextEdge[E];

set <pair <int, int> > edges;

void addEdge(int u, int v) {
	if (edges.find(make_pair(u, v)) == edges.end()) {
		edges.insert(make_pair(u, v));
		to[edgeCount] = v;
		nextEdge[edgeCount] = firstEdge[u];
		firstEdge[u] = edgeCount++;
	}
}

int Next[E];
bool visit[E];

int main() {
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> End[i];
		points.push_back(End[i]);
	}

	for (int i = 0; i + 1 < n; ++i) {
		for (int j = i + 1; j + 1 < n; ++j) {
			if (signum(det(End[i + 1] - End[i], End[j + 1] - End[j]) / (End[i + 1] - End[i]).norm()) != 0) {
				points.push_back(intersect(End[i], End[i + 1], End[j], End[j + 1]));
			}
		}
	}
	sort(points.begin(), points.end());
	points.erase(unique(points.begin(), points.end()), points.end());
	edgeCount = 0;
	memset(firstEdge, -1, sizeof(firstEdge)); //int edgeCount, firstEdge[V],
	for (int i = 0; i + 1 < n;  ++i)
	{
		vector <pair <double, int> > events;
		for (int k = 0; k < (int)points.size(); ++k) {
			if (points[k].on(End[i], End[i + 1])) {  //看点k 是否在?段p[i],p[i+1]上
				events.push_back(make_pair((points[k] - End[i]).norm(), k));
			}
		}
		sort(events.begin(), events.end());
		for (int k = 0; k + 1 < (int)events.size(); ++k) {
			addEdge(events[k].second, events[k + 1].second);
			addEdge(events[k + 1].second, events[k].second);
		}

		
		
	}
	for (int i = 0; i < (int)points.size(); ++i) {
		vector <pair <double, int> > events;
		for (int iter = firstEdge[i]; iter != -1; iter = nextEdge[iter]) {
			events.push_back(make_pair((points[to[iter]] - points[i]).arg(), iter));
		}
		sort(events.begin(), events.end());
		for (int k = 0; k < (int)events.size(); ++k) {
			Next[events[(k + 1) % (int)events.size()].second ^ 1] = events[k].second;
		}
	}


	double result = 0;
	memset(visit, 0, sizeof(visit));
	for (int i = 0; i < edgeCount; ++i) {
		if (!visit[i]) {
			double ret = 0;
			int p = i;
			while (!visit[p]) {
				visit[p] = true;
				ret += det(points[to[p ^ 1]], points[to[p]]);
				p = Next[p];
			} 
			if (p == i && signum(ret) > 0) {
				result += ret;
			}
		}
	}                           
	printf("%.8f\n", result / 2.0);
	return 0;
}