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<cstdio>
#include<complex>
#include<vector>
#include<cmath>
#include<utility>
#include<algorithm>

using namespace std;

typedef complex<double> Point;
typedef complex<double> Vector;
typedef pair<Point,Point> Line;
typedef pair<Point,Point> Segment;
typedef vector<Point> Polygon;

vector<Point> points;
vector<bool> valid;
vector<Point> tmp;

const double eps=1e-9;

template<class T> bool eq(T a,T b){
	return abs(a-b)<eps;
}

double crP(Vector a,Vector b){
	return (conj(a)*b).imag();
}

bool onSeg(Segment s,Point p){
	Point a=s.first,b=s.second;
	return eq(abs(a-b),abs(a-p)+abs(b-p));
}

Point iLL(Line l1,Line l2){
	Point p1=l1.first,p2=l1.second;
	Point q1=l2.first,q2=l2.second;
	if(eq(crP(p2-p1,q2-q1),0.0)){
		Point p=Point(NAN,NAN);
		return p;
	}
	double den=crP(p2-p1,q2-q1);
	double num=crP(q1-p1,q2-p1);
	return p1+(p2-p1)*(num/den);
}

Point iSS(Segment s1,Segment s2){
	Point pt=iLL(s1,s2);
	if(isnan(pt.real())) return pt;
	if(onSeg(s1,pt)&&onSeg(s2,pt)) return pt;
	return Point(NAN,NAN);
}

vector<Point> polyline;
vector<int> vs[110];
int N;
int V;

Point center;
bool cmp_distance(const int &i1,const int &i2){
	return abs(points[i1]-center)<abs(points[i2]-center);
}
bool cmp_angle(const int &i1,const int &i2){
	Point p1=points[i1]-center,p2=points[i2]-center;
	double x1=p1.real(),y1=p1.imag();
	double x2=p2.real(),y2=p2.imag();
	return atan2(y1,x1)+eps<atan2(y2,x2);
}

vector<int> G[100*100+100];
vector<bool> used[100*100+100];

vector<Polygon> polygons;

void stroke(Polygon &poly,int prev,int cur,int st1,int st2);

void getPolygons(){
	for(int i=0;i<V;i++){
		center=points[i];
		sort(G[i].begin(),G[i].end(),cmp_angle);
	}
	center=points[2];
	int target=4;
	for(int i=0;i<V;i++){
		for(int j=0;j<G[i].size();j++){
			if(used[i][j]) continue;
			Polygon poly;
			stroke(poly,i,G[i][j],i,G[i][j]);
			polygons.push_back(poly);
		}
	}
}

int dep=0;

void stroke(Polygon &poly,int prev,int cur,int st1,int st2){
	poly.push_back(points[cur]);
	center=points[cur];
	int id=distance(G[cur].begin(),lower_bound(G[cur].begin(),G[cur].end(),prev,cmp_angle));
	int nxtId=(id+1)%(G[cur].size());
	int nxt=G[cur][nxtId];
	if(st1==cur&&st2==nxt) return;
	used[cur][nxtId]=true;
	stroke(poly,cur,nxt,st1,st2);
}

double getArea(Polygon poly){
	double res=0;
	for(int i=0;i<poly.size();i++){
		Point p1=poly[i];
		Point p2=poly[(i+1)%poly.size()];
		double tmp=crP(p1,p2);
		res+=tmp;
	}
	res/=2;
	return abs(res);
}

int main(){
	scanf("%d",&N);
	for(int i=0;i<N;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		polyline.push_back(Point(x,y));
		points.push_back(Point(x,y));
	}
	for(int i=0;i<N-1;i++) for(int j=i+1;j<N-1;j++){
		if(eq(crP(polyline[i+1]-polyline[i],polyline[j+1]-polyline[j]),0.0)){
			continue;
		}
		Segment seg1=Segment(polyline[i],polyline[i+1]);
		Segment seg2=Segment(polyline[j],polyline[j+1]);
		Point pt=iSS(seg1,seg2);
		if(isnan(pt.real())){
			continue;
		}
		points.push_back(pt);
	}
	for(int i=0;i<points.size();i++){
		bool flg=true;
		for(int j=0;j<i;j++){
			if(eq(points[i],points[j])){
				flg=false;
			}
		}
		valid.push_back(flg);
	}
	for(int i=0;i<points.size();i++){
		if(valid[i]) tmp.push_back(points[i]);
	}
	points=tmp;
	V=points.size();
	for(int i=0;i<N-1;i++){
		Segment seg=Segment(polyline[i],polyline[i+1]);
		for(int j=0;j<points.size();j++){
			if(onSeg(seg,points[j])){
				vs[i].push_back(j);
			}
		}
	}
	for(int i=0;i<N-1;i++){
		center=polyline[i];
		sort(vs[i].begin(),vs[i].end(),cmp_distance);
		for(int j=0;j+1<vs[i].size();j++){
			//connect vs[i][j]-vs[i][j+1]
			int u=vs[i][j],v=vs[i][j+1];
			G[u].push_back(v);
			G[v].push_back(u);
		}
	}
	for(int i=0;i<V;i++){
		sort(G[i].begin(),G[i].end());
		G[i].erase(unique(G[i].begin(),G[i].end()),G[i].end());
		for(int j=0;j<G[i].size();j++) used[i].push_back(false);
	}
	getPolygons();
	double ans=0;
	for(int i=0;i<polygons.size();i++){
		double cur=getArea(polygons[i]);
		ans+=cur;
	}
	printf("%.9f\n",ans/2);
	return 0;
}