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

using namespace std;

const long double eps = 1e-8;
const long double pi = acos(-1);
int dcmp(long double x)
{
    if (fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}

struct Point
{
    long double x, y;
    Point(long double x = 0, long double y = 0) : x(x), y(y) {}
    bool operator < (const Point& rhs) const
    {
        return x < rhs.x || (x == rhs.x && y < rhs.y);
    }
    bool operator == (const Point& rhs) const
    {
        return dcmp(x - rhs.x) == 0 && dcmp(y - rhs.y) == 0;
    }
};

typedef Point Vector;

Vector operator - (const Point& A, const Point& B)
{
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator + (const Point& A, const Point& B)
{
    return Vector(A.x + B.x, A.y + B.y);
}

Vector operator * (const Point& A, const long double& B)
{
    return Vector(A.x * B, A.y * B);
}

long double Cross(const Vector& A, const Vector& B)
{
    return A.x * B.y - A.y * B.x;
}

long double Dot(const Vector& A, const Vector& B)
{
    return A.x * B.x + A.y * B.y;
}

long double Length(const Vector& A)
{
    return sqrt(Dot(A, A));
}

long double RelativeAngle(const Vector& A, const Vector& B)
{
    long double c = Dot(A, B) / Length(A) / Length(B);
    if (c > 1) c = 1;
    else if (c < -1) c = -1;
    long double angle = acos(c);
    if (Cross(A, B) < 0) angle = pi * 2 - angle;
    return angle;
}

bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
{
    long double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
            c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
    return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}

Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
{
    Vector u = P - Q;
    long double t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}

bool OnSegment(Point p, Point a1, Point a2)
{
    return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) <= 0;
}

Point s[100];
vector<Point> p;
vector<vector<pair<int, int> > > G;
vector<bool> vis;
int sz = 0;

int main()
{
    int N;
    scanf("%d", &N);
    for (int i = 0; i < N; ++i)
    {
        double x, y;
        scanf("%lf %lf", &x, &y);
        s[i].x = x;
        s[i].y = y;
        p.push_back(s[i]);
    }
    for (int i = 0; i < N - 1; ++i)
    {
        Point a1 = s[i];
        Point a2 = s[i + 1];
        for (int j = i + 1; j < N - 1; ++j)
        {
            Point b1 = s[j];
            Point b2 = s[j + 1];
            if (SegmentProperIntersection(a1, a2, b1, b2))
            {
                p.push_back(GetLineIntersection(a1, a2 - a1, b1, b2 - b1));
            }
        }
    }
    sort(p.begin(), p.end());
    p.erase(unique(p.begin(), p.end()), p.end());
    G.resize(p.size());
    for (int i = 0; i < N - 1; ++i)
    {
        Point a1 = s[i];
        Point a2 = s[i + 1];
        vector<pair<long double, int> > tmp;
        for (int j = 0; j < p.size(); ++j)
        {
            if (OnSegment(p[j], a1, a2))
            {
                tmp.push_back(make_pair(Length(p[j] - a1), j));
            }
        }
        sort(tmp.begin(), tmp.end());
        for (int j = 0; j < tmp.size() - 1; ++j)
        {
            G[tmp[j].second].push_back(make_pair(tmp[j + 1].second, 0));
            G[tmp[j + 1].second].push_back(make_pair(tmp[j].second, 0));
        }
    }
    for (int i = 0; i < p.size(); ++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)
        {
            G[i][j].second = sz++;
        }
    }
    vis.resize(sz, 0);
    int from = 0;
    int to = G[0][0].first;
    for (int i = 1; i < G[0].size(); ++i)
    {
        int v = G[0][i].first;
        if (atan2(p[v].y - p[0].y, p[v].x - p[0].x) <
            atan2(p[to].y - p[0].y, p[to].x - p[0].x))
        {
            to = v;
        }
    }
    long double area = 0;
    do
    {
        int nto = from;
        int fromidx = 0;
        int idx = 0;
        long double angle = 1e9;
        for (int i = 0; i < G[to].size(); ++i)
        {
            int v = G[to][i].first;
            if (v == from)
            {
                fromidx = G[to][i].second;
                continue;
            }
            if (vis[G[to][i].second]) continue;
            long double nangle = RelativeAngle(p[from] - p[to], p[v] - p[to]);
            if (nangle < angle) nto = v, angle = nangle, idx = G[to][i].second;
        }
        if (nto == from) idx = fromidx;
        if (vis[idx]) while (1);
        vis[idx] = true;
        area += Cross(p[from], p[to]) / 2;
        from = to;
        to = nto;
    }
    while (from);
    printf("%.10f\n", (double)area);
    return 0;
}