Problem p01562 (C++) — buggy submission, verdict: Runtime Error

//
// 22 line ???????????????
//
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <vector>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x, a)                                                             \\
  {                                                                            \\
    auto y = (x);                                                              \\
    if (sign(y - a)) {                                                         \\
      cout << "line " << __LINE__ << #x << " = " << y << " != " << a << endl;  \\
      exit(-1);                                                                \\
    }                                                                          \\
  }

#define dout                                                                   \\
  if (0)                                                                       \\
  cout

double urand() { return rand() / (1.0 + RAND_MAX); }

const double PI = acos(-1.0);

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
// notice: should be normalize to O(1)
const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS)
    return -1;
  if (x > +EPS)
    return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y;
  point &operator+=(point p) {
    x += p.x;
    y += p.y;
    return *this;
  }
  point &operator*=(T a) {
    x *= a;
    y *= a;
    return *this;
  }
  point &operator-=(point p) {
    x -= p.x;
    y -= p.y;
    return *this;
  }
  point &operator/=(T a) { return *this *= (1.0 / a); }
  point operator-() const { return {-x, -y}; }
  bool operator<(point p) const {
    if (sign(x - p.x))
      return sign(x - p.x) < 0;
    return sign(y - p.y) < 0;
  }
};
bool operator>(point p, point q) { return q < p; }
bool operator<=(point p, point q) { return !(q < p); }
bool operator>=(point p, point q) { return !(p < q); }
bool operator==(point p, point q) { return !(p < q) && !(q < p); }
bool operator!=(point p, point q) { return (p < q) || !(q < p); }
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x * q.x + p.y * q.y; }
point::T cross(point p, point q) {
  return p.x * q.y - p.y * q.x;
} // left turn > 0
point::T norm2(point p) { return dot(p, p); }
point orth(point p) { return {-p.y, p.x}; }
point::T norm(point p) { return sqrt(dot(p, p)); }

int sign_dot(point p, point q) {
  double a = norm(p), b = norm(q);
  if (sign(a) == 0 || sign(b) == 0)
    return 0;
  return sign(dot(p, q) / a / b);
}
int sign_cross(point p, point q) {
  double a = norm(p), b = norm(q);
  if (sign(a) == 0 || sign(b) == 0)
    return 0;
  return sign(cross(p, q) / a / b);
}

ostream &operator<<(ostream &os, const point &p) {
  os << "(" << p.x << "," << p.y << ")";
  return os;
}

struct segment {
  point p, q;
};

// s.p + A (s.q - s.p) == t.p + B (t.q - t.p)
// A (s.q - s.p) == t.p - s.p + B (t.q - t.p)
// A = (t.p - s.p)x(t.q - t.p)/(s.q - s.p)x(t.q - t.p)
//

vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p);
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) {
    a = -a;
    b = -b;
    c = -c;
  }
  if (sign(b) < 0 || sign(a - b) < 0 || sign(c) < 0 || sign(a - c) < 0)
    return {}; // disjoint
  if (sign(a) != 0)
    return {s.p + b / a * (s.q - s.p)}; // properly crossing
  vector<point> ps;                     // same line
  auto insert_if_possible = [&](point p) {
    for (auto q : ps)
      if (sign(dot(p - q, p - q)) == 0)
        return;
    ps.push_back(p);
  };
  if (sign(dot(s.p - t.p, s.q - t.p)) <= 0)
    insert_if_possible(t.p);
  if (sign(dot(s.p - t.q, s.q - t.q)) <= 0)
    insert_if_possible(t.q);
  if (sign(dot(t.p - s.p, t.q - s.p)) <= 0)
    insert_if_possible(s.p);
  if (sign(dot(t.p - s.q, t.q - s.q)) <= 0)
    insert_if_possible(s.q);
  return ps;
}

/*
  struct Face {
    Edge *edge; // Any edge incident to this face (CCW)
    vector<point> ps;
  };
*/

//
// Verified: AOJ1226
//
struct arrangement {
  // Doubly Connected Edge List, aka., DCEL
  struct Vertex;
  struct Edge;
  struct Vertex {
    point p;    //
    Edge *edge; // any edge incident to this vertex
  };
  struct Edge {
    Vertex *vertex;    // origin vertex of the edge
    Edge *twin;        // reverse edge of e
    Edge *prev, *next; // surrounding edges of face (CCW)
  };
  vector<Vertex *> vertices;
  vector<Edge *> edges;

  // Segments
  vector<segment> segs;

  // Sweep-Line Structure (RBST)
  struct node {
    int index;
    int size = 1;
    node *left = 0, *right = 0;
  } *root = 0;
  int size(node *x) { return x ? x->size : 0; }
  vector<node> ns;

  node *update(node *x) {
    if (x)
      x->size = 1 + size(x->left) + size(x->right);
    return x;
  }
  node *merge(node *x, node *y) {
    if (!x)
      return y;
    if (!y)
      return x;
    if (rand() % (x->size + y->size) < x->size) {
      x->right = merge(x->right, y);
      return update(x);
    } else {
      y->left = merge(x, y->left);
      return update(y);
    }
  }
  template <class C> // 3-way split: cond(x) < 0, cond(x) == 0, cond(x) > 0
  tuple<node *, node *, node *> split(node *x, C cond) {
    if (!x)
      return make_tuple(x, x, x);
    if (cond(x) == 0) {
      auto a = split(x->left, cond);
      auto b = split(x->right, cond);
      assert(get<2>(a) == 0);
      if (get<0>(b)) {
        cout << "error on processing " << x->index << endl;
        cout << get<0>(b) << " " << get<1>(b) << " " << get<2>(b) << endl;
      }
      assert(get<0>(b) == 0);
      x->left = x->right = 0;
      update(x);
      get<1>(a) = merge(merge(get<1>(a), x), get<1>(b));
      get<2>(a) = get<2>(b);
      return a;
    }
    if (cond(x) < 0) {
      auto a = split(x->right, cond);
      x->right = 0;
      update(x);
      get<0>(a) = merge(x, get<0>(a));
      return a;
    }
    if (cond(x) > 0) {
      auto a = split(x->left, cond);
      x->left = 0;
      update(x);
      get<2>(a) = merge(get<2>(a), x);
      return a;
    }
  }
  template <class F> void process(node *x, F func) {
    if (!x)
      return;
    process(x->left, func);
    func(x);
    process(x->right, func);
  }
  node *leftmost(node *x) {
    while (x && x->left)
      x = x->left;
    return x;
  }
  node *rightmost(node *x) {
    while (x && x->right)
      x = x->right;
    return x;
  }

  set<point> events;
  void display(node *x, int tab = 0) {
    if (!x)
      return;
    const point &p = *events.begin();
    display(x->left, tab + 2);

    auto cond = [&](node *x) {
      const segment &s = segs[x->index];
      // assert(sign(s.p.x - p.x) <= 0);
      // assert(sign(s.q.x - p.x) >= 0);
      if (sign(s.q.x - s.p.x) == 0) {
        if (sign(p.y - s.p.y) < 0)
          return -1;
        if (sign(s.q.y - p.y) < 0)
          return +1;
        return 0;
      }
      return -sign_cross(s.p - p, s.q - p);
    };

    dout << string(tab, ' ') << x->index << " (" << segs[x->index].p << ","
         << segs[x->index].q << ") " << cond(x) << endl;
    display(x->right, tab + 2);
  }

  // merge overlapping segments?
  void preprocess() {
    for (int i = 0; i < segs.size(); ++i) {
      if (segs[i].q < segs[i].p)
        swap(segs[i].p, segs[i].q);
    }
  }
  // ??? uniqueness ?????????????????§?????? uniqueness ??§???
  arrangement(vector<segment> segs_) : segs(segs_) {
    preprocess();
    ns.resize(segs.size());
    map<point, set<int>> L, R;

    for (int i = 0; i < segs.size(); ++i) {
      dout << i << ": " << segs[i].p << " " << segs[i].q << endl;
    }

    // map<Vertex*, vector<Edge*>> inc;
    map<Vertex *, map<Vertex *, Edge *>> adj;

    for (int i = 0; i < segs.size(); ++i) {
      events.insert(segs[i].p);
      events.insert(segs[i].q);
      L[segs[i].p].insert(i);
      R[segs[i].q].insert(i);
      ns[i].index = i;
    }
    vector<Vertex *> last(segs.size());

    while (!events.empty()) {
      const point p = *events.begin();
      Vertex *u = new Vertex({p});
      vertices.push_back(u);

      dout << "processing " << p << endl;
      display(root);
      events.erase(events.begin());

      auto cond = [&](node *x) {
        const segment &s = segs[x->index];
        assert(sign(s.p.x - p.x) <= 0);
        assert(sign(s.q.x - p.x) >= 0);
        if (sign(s.q.x - s.p.x) == 0) {
          dout << "  horizontal segment " << x->index << " is: ";
          if (sign(p.y - s.p.y) < 0)
            dout << "-1" << endl;
          if (sign(s.q.y - p.y) < 0)
            dout << "+1" << endl;
          if (sign(p.y - s.p.y) < 0)
            return -1;
          if (sign(s.q.y - p.y) < 0)
            return +1;
          dout << "0" << endl;
          return 0;
        }
        // cross ???????????????????????????
        // s.p + t (s.q - s.p) = p
        dout << "  segment " << x->index << " is: ";
        dout << -sign_cross(s.p - p, s.q - p) << endl;
        return -sign_cross(s.p - p, s.q - p);
      };
      auto z = split(root, cond);
      dout << "split: " << get<0>(z) << " " << get<1>(z) << " " << get<2>(z)
           << endl;
      vector<node *> inserter;
      dout << "segments on " << p << ":";
      process(get<1>(z), [&](node *x) {
        dout << " " << x->index;
        Vertex *v = last[x->index];
        assert(v != 0);
        if (!adj[u][v]) {
          adj[u][v] = new Edge({u});
          adj[v][u] = new Edge({v});
          adj[u][v]->twin = adj[v][u];
          adj[v][u]->twin = adj[u][v];
          edges.push_back(adj[u][v]);
          edges.push_back(adj[v][u]);
        }
        /*
        Edge *e = new Edge({u}), *r = new Edge({v});
        e->twin = r; r->twin = e;
        edges.push_back(e);
        edges.push_back(r);
        inc[u].push_back(e);
        inc[v].push_back(r);
        */
        if (!R[p].count(x->index))
          inserter.push_back(x);
      });
      dout << endl;
      for (int i : L[p]) {
        if (!R[p].count(i))
          inserter.push_back(&ns[i]);
      }
      sort(all(inserter), [&](node *x, node *y) {
        // x ??????????????????????°??????? ==> x -> y ??? ccw order
        // order at (p + epsilon) ??§?????????;
        // we can assume that the segments contain p
        // ==> ??????????????§??????
        //
        const segment &s = segs[x->index], &t = segs[y->index];
        return sign_cross(s.q - s.p, t.q - t.p) >= 0;
      });
      auto add_event = [&](node *x, node *y) {
        if (!x || !y)
          return;
        dout << "add event, p = " << p << endl;
        vector<point> ps = intersect(segs[x->index], segs[y->index]);
        for (point q : ps) {
          dout << "crosspoint of " << x->index << " and " << y->index << " is "
               << q << endl;
          if (p < q) {
            dout << " ==> inserted" << endl;
            events.insert(q);
          } else {
            dout << " ==> ignored (" << p << " vs " << q << ") = " << (p < q)
                 << endl;
          }
        }
        return;
      };
      if (inserter.empty()) {
        add_event(rightmost(get<0>(z)), leftmost(get<2>(z)));
      } else {
        add_event(rightmost(get<0>(z)), inserter[0]);
        add_event(leftmost(get<2>(z)), inserter.back());
      }
      root = 0;
      for (int i = 0; i < inserter.size(); ++i) {
        last[inserter[i]->index] = u;
        dout << "insert " << inserter[i]->index << endl;
        inserter[i]->left = inserter[i]->right = 0;
        root = merge(root, update(inserter[i]));
      }
      root = merge(merge(get<0>(z), root), get<2>(z));
    }
    for (auto &pp : adj) {
      Vertex *u = pp.fst;
      vector<Edge *> es;
      for (auto z : pp.snd)
        es.push_back(z.snd);
      sort(all(es), [&](Edge *e, Edge *f) {
        assert(e->vertex == f->vertex);
        auto quad = [](point p) {
          for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
            if (p.x > 0 && p.y >= 0)
              return i;
          return 0;
        };
        const point p = e->twin->vertex->p - e->vertex->p;
        const point q = f->twin->vertex->p - f->vertex->p;
        if (quad(p) != quad(q))
          return quad(p) < quad(q);
        return sign_cross(p, q) > 0;
      });
      // cout << "vertex " << u->p << endl;
      u->edge = es.back();
      for (Edge *e : es) {
        // cout << "  edge " << e << ": " << e->vertex->p << " " <<
        // e->twin->vertex->p << "; " << e->twin << endl;
        u->edge->next = e;
        u->edge->next->prev = u->edge;
        u->edge = u->edge->next;
      }
    }

    /*
        for (auto &pp: inc) {
          Vertex *u = pp.fst;
          vector<Edge*> &es = pp.snd;
          sort(all(inc[u]), [&](Edge *e, Edge *f) {
            assert(e->vertex == f->vertex);
            auto quad = [](point p) {
              for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
                if (p.x > 0 && p.y >= 0) return i;
              return 0;
            };
            const point p = e->twin->vertex->p - e->vertex->p;
            const point q = f->twin->vertex->p - f->vertex->p;
            if (quad(p) != quad(q)) return quad(p) < quad(q);
            if (sign(cross(p, q))) return sign(cross(p, q)) > 0;
            return cross(p, q) > 0;
          });
          cout << "vertex " << u->p << endl;
          u->edge = es.back();
          for (Edge *e: es) {
            cout << "  edge " << e << ": " << e->vertex->p << " " <<
       e->twin->vertex->p << "; " << e->twin << endl; u->edge->next = e;
            u->edge->next->prev = u->edge;
            u->edge = u->edge->next;
          }
        }
        */
  }
};

void AOJ1226() {
  for (int n; ~scanf("%d", &n) && n;) {
    // cout << n << endl;
    vector<vector<double>> a(4, vector<double>(n));
    for (int k = 0; k < 4; ++k)
      for (int i = 0; i < n; ++i)
        scanf("%lf", &a[k][i]);

    vector<segment> ss = {
        {{0, 0}, {0, 1}}, {{0, 1}, {1, 1}}, {{1, 1}, {1, 0}}, {{1, 0}, {0, 0}}};
    for (int i = 0; i < n; ++i) {
      ss.push_back({{a[0][i], 0}, {a[1][i], 1}});
      ss.push_back({{0, a[2][i]}, {1, a[3][i]}});
    }
    arrangement arr(ss);

    double result = 0;
    set<arrangement::Edge *> seen;
    for (auto *e : arr.edges) {
      if (seen.count(e))
        continue;
      auto *f = e;
      double area = 0;
      do {
        seen.insert(f);
        area += cross(f->vertex->p, f->twin->vertex->p);
        f = f->twin->prev;
      } while (f != e);
      result = max(result, area);
    }
    printf("%.6f\\n", result / 2);
  }
}
//
// s.p + a (s.q - s.p) == t.p + b (t.q - t.p)
// ????§£?????????????????????????????\\?????°????????? a ???????????? a*
// ?????????
//

void AOJ2448() {
  int n;
  scanf("%d", &n);
  vector<point> ps(n);
  for (int i = 0; i < n; ++i)
    scanf("%lf %lf", &ps[i].x, &ps[i].y);
  vector<segment> ss;
  for (int i = 0; i + 1 < n; ++i)
    ss.push_back({ps[i], ps[i + 1]});
  arrangement arr(ss);

  double result = 0;
  set<arrangement::Edge *> seen;
  for (auto *e : arr.edges) {
    if (seen.count(e))
      continue;
    auto *f = e;
    double area = 0;
    do {
      seen.insert(f);
      area += cross(f->vertex->p, f->twin->vertex->p);
      f = f->twin->prev;
    } while (f != e);
    if (area > 0)
      result += area;
  }
  printf("%.12f\\n", result / 2);
}

int main() {
  // AOJ1226();
  AOJ2448();
  return 0;
  /*
  for (int seed =0; seed < 10000; ++seed) {
    cout << "seed = " << seed << endl;
    srand(seed);
    int n = 100;
    vector<segment> ss;
    int x = 0, y = 0;
    for (int i = 0; i < n; ++i) {
      int z = rand() % n, w = rand() % n;
      ss.push_back({{x,y},{z,w}});
      x = z; y = w;
      //cout << ss.back().p << " " << ss.back().q << endl;
    }
    arrangement arr(ss);
  }
  */
  /*
  ss.push_back({{0,0},{3,2}});
  ss.push_back({{0,1},{3,1}});
  ss.push_back({{2,0},{2,4}});
  //ss.push_back({{0,3},{3,2}});
  //ss.push_back({{1.5,0},{1.5,4}});
  //
  */

  /*
  auto *v = arr.get({1,1});
  auto *e = v->edge;
  do {
    cout << e->vertex->p << " -- " << e->twin->vertex->p << endl;
    e = e->next;
  } while (e != v->edge);
  */
}

Error: WA

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <vector>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x, a)                                                             \\
  {                                                                            \\
    auto y = (x);                                                              \\
    if (sign(y - a)) {                                                         \\
      cout << "line " << __LINE__ << #x << " = " << y << " != " << a << endl;  \\
      exit(-1);                                                                \\
    }                                                                          \\
  }

#define dout                                                                   \\
  if (0)                                                                       \\
  cout

double urand() { return rand() / (1.0 + RAND_MAX); }

const double PI = acos(-1.0);

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
// notice: should be normalize to O(1)
const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS)
    return -1;
  if (x > +EPS)
    return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y;
  point &operator+=(point p) {
    x += p.x;
    y += p.y;
    return *this;
  }
  point &operator*=(T a) {
    x *= a;
    y *= a;
    return *this;
  }
  point &operator-=(point p) {
    x -= p.x;
    y -= p.y;
    return *this;
  }
  point &operator/=(T a) { return *this *= (1.0 / a); }
  point operator-() const { return {-x, -y}; }
  bool operator<(point p) const {
    if (sign(x - p.x))
      return sign(x - p.x) < 0;
    return sign(y - p.y) < 0;
  }
};
bool operator>(point p, point q) { return q < p; }
bool operator<=(point p, point q) { return !(q < p); }
bool operator>=(point p, point q) { return !(p < q); }
bool operator==(point p, point q) { return !(p < q) && !(q < p); }
bool operator!=(point p, point q) { return (p < q) || !(q < p); }
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x * q.x + p.y * q.y; }
point::T cross(point p, point q) {
  return p.x * q.y - p.y * q.x;
} // left turn > 0
point::T norm2(point p) { return dot(p, p); }
point orth(point p) { return {-p.y, p.x}; }
point::T norm(point p) { return sqrt(dot(p, p)); }

ostream &operator<<(ostream &os, const point &p) {
  os << "(" << p.x << "," << p.y << ")";
  return os;
}

struct segment {
  point p, q;
};

vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p);
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) {
    a = -a;
    b = -b;
    c = -c;
  }
  if (sign(b) < 0 || sign(a - b) < 0 || sign(c) < 0 || sign(a - c) < 0)
    return {}; // disjoint
  if (sign(a) != 0)
    return {s.p + b / a * (s.q - s.p)}; // properly crossing
  vector<point> ps;                     // same line
  auto insert_if_possible = [&](point p) {
    for (auto q : ps)
      if (sign(dot(p - q, p - q)) == 0)
        return;
    ps.push_back(p);
  };
  if (sign(dot(s.p - t.p, s.q - t.p)) <= 0)
    insert_if_possible(t.p);
  if (sign(dot(s.p - t.q, s.q - t.q)) <= 0)
    insert_if_possible(t.q);
  if (sign(dot(t.p - s.p, t.q - s.p)) <= 0)
    insert_if_possible(s.p);
  if (sign(dot(t.p - s.q, t.q - s.q)) <= 0)
    insert_if_possible(s.q);
  return ps;
}

/*
  struct Face {
    Edge *edge; // Any edge incident to this face (CCW)
    vector<point> ps;
  };
*/

//
// Verified: AOJ1226
//
struct arrangement {
  // Doubly Connected Edge List, aka., DCEL
  struct Vertex;
  struct Edge;
  struct Vertex {
    point p;    //
    Edge *edge; // any edge incident to this vertex
  };
  struct Edge {
    Vertex *vertex;    // origin vertex of the edge
    Edge *twin;        // reverse edge of e
    Edge *prev, *next; // surrounding edges of face (CCW)
  };
  vector<Vertex *> vertices;
  vector<Edge *> edges;

  // Segments
  vector<segment> segs;

  // Sweep-Line Structure (RBST)
  struct node {
    int index;
    int size = 1;
    node *left = 0, *right = 0;
  } *root = 0;
  int size(node *x) { return x ? x->size : 0; }
  vector<node> ns;

  node *update(node *x) {
    if (x)
      x->size = 1 + size(x->left) + size(x->right);
    return x;
  }
  node *merge(node *x, node *y) {
    if (!x)
      return y;
    if (!y)
      return x;
    if (rand() % (x->size + y->size) < x->size) {
      x->right = merge(x->right, y);
      return update(x);
    } else {
      y->left = merge(x, y->left);
      return update(y);
    }
  }
  template <class C> // 3-way split: cond(x) < 0, cond(x) == 0, cond(x) > 0
  tuple<node *, node *, node *> split(node *x, C cond) {
    if (!x)
      return make_tuple(x, x, x);
    if (cond(x) == 0) {
      auto a = split(x->left, cond);
      auto b = split(x->right, cond);
      assert(get<2>(a) == 0);
      if (get<0>(b)) {
        cout << "error on processing " << x->index << endl;
        cout << get<0>(b) << " " << get<1>(b) << " " << get<2>(b) << endl;
      }
      assert(get<0>(b) == 0);
      x->left = x->right = 0;
      update(x);
      get<1>(a) = merge(merge(get<1>(a), x), get<1>(b));
      get<2>(a) = get<2>(b);
      return a;
    }
    if (cond(x) < 0) {
      auto a = split(x->right, cond);
      x->right = 0;
      update(x);
      get<0>(a) = merge(x, get<0>(a));
      return a;
    }
    if (cond(x) > 0) {
      auto a = split(x->left, cond);
      x->left = 0;
      update(x);
      get<2>(a) = merge(get<2>(a), x);
      return a;
    }
  }
  template <class F> void process(node *x, F func) {
    if (!x)
      return;
    process(x->left, func);
    func(x);
    process(x->right, func);
  }
  node *leftmost(node *x) {
    while (x && x->left)
      x = x->left;
    return x;
  }
  node *rightmost(node *x) {
    while (x && x->right)
      x = x->right;
    return x;
  }

  set<point> events;
  void display(node *x, int tab = 0) {
    if (!x)
      return;
    const point &p = *events.begin();
    display(x->left, tab + 2);

    auto cond = [&](node *x) {
      const segment &s = segs[x->index];
      assert(sign(s.p.x - p.x) <= 0);
      assert(sign(s.q.x - p.x) >= 0);
      if (sign(s.q.x - s.p.x) == 0) {
        if (sign(p.y - s.p.y) < 0)
          return -1;
        if (sign(s.q.y - p.y) < 0)
          return +1;
        return 0;
      }
      return -sign(cross(s.p - p, s.q - p));
    };

    dout << string(tab, ' ') << x->index << " (" << segs[x->index].p << ","
         << segs[x->index].q << ") " << cond(x) << endl;
    display(x->right, tab + 2);
  }

  // merge overlapping segments?
  void preprocess() {
    for (int i = 0; i < segs.size(); ++i) {
      if (segs[i].q < segs[i].p)
        swap(segs[i].p, segs[i].q);
    }
  }
  // ??? uniqueness ?????????????????§?????? uniqueness ??§???
  arrangement(vector<segment> segs_) : segs(segs_) {
    preprocess();
    ns.resize(segs.size());
    map<point, set<int>> L, R;

    // map<Vertex*, vector<Edge*>> inc;
    map<Vertex *, map<Vertex *, Edge *>> adj;

    for (int i = 0; i < segs.size(); ++i) {
      events.insert(segs[i].p);
      events.insert(segs[i].q);
      L[segs[i].p].insert(i);
      R[segs[i].q].insert(i);
      ns[i].index = i;
    }
    vector<Vertex *> last(segs.size());

    while (!events.empty()) {
      const point p = *events.begin();
      Vertex *u = new Vertex({p});
      vertices.push_back(u);

      dout << "processing " << p << endl;
      display(root);
      events.erase(events.begin());

      auto cond = [&](node *x) {
        const segment &s = segs[x->index];
        assert(sign(s.p.x - p.x) <= 0);
        assert(sign(s.q.x - p.x) >= 0);
        if (sign(s.q.x - s.p.x) == 0) {
          dout << "  horizontal segment " << x->index << " is: ";
          if (sign(p.y - s.p.y) < 0)
            dout << "-1" << endl;
          if (sign(s.q.y - p.y) < 0)
            dout << "+1" << endl;
          if (sign(p.y - s.p.y) < 0)
            return -1;
          if (sign(s.q.y - p.y) < 0)
            return +1;
          dout << "0" << endl;
          return 0;
        }
        dout << "  segment " << x->index << " is: ";
        dout << -sign(cross(s.p - p, s.q - p)) << endl;
        return -sign(cross(s.p - p, s.q - p));
      };
      auto z = split(root, cond);
      dout << "split: " << get<0>(z) << " " << get<1>(z) << " " << get<2>(z)
           << endl;
      vector<node *> inserter;
      dout << "segments on " << p << ":";
      process(get<1>(z), [&](node *x) {
        dout << " " << x->index;
        Vertex *v = last[x->index];
        assert(v != 0);
        if (!adj[u][v]) {
          adj[u][v] = new Edge({u});
          adj[v][u] = new Edge({v});
          adj[u][v]->twin = adj[v][u];
          adj[v][u]->twin = adj[u][v];
          edges.push_back(adj[u][v]);
          edges.push_back(adj[v][u]);
        }
        /*
        Edge *e = new Edge({u}), *r = new Edge({v});
        e->twin = r; r->twin = e;
        edges.push_back(e);
        edges.push_back(r);
        inc[u].push_back(e);
        inc[v].push_back(r);
        */
        if (!R[p].count(x->index))
          inserter.push_back(x);
      });
      dout << endl;
      for (int i : L[p]) {
        inserter.push_back(&ns[i]);
      }
      sort(all(inserter), [&](node *x, node *y) {
        // x ??????????????????????°??????? ==> x -> y ??? ccw order
        // order at (p + epsilon) ??§?????????;
        // we can assume that the segments contain p
        // ==> ??????????????§??????
        //
        const segment &s = segs[x->index], &t = segs[y->index];
        return sign(cross(s.q - s.p, t.q - t.p)) >= 0;
      });
      auto add_event = [&](node *x, node *y) {
        if (!x || !y)
          return;
        dout << "add event, p = " << p << endl;
        vector<point> ps = intersect(segs[x->index], segs[y->index]);
        for (point q : ps) {
          dout << "crosspoint of " << x->index << " and " << y->index << " is "
               << q << endl;
          if (p < q) {
            dout << " ==> inserted" << endl;
            events.insert(q);
          } else {
            dout << " ==> ignored (" << p << " vs " << q << ") = " << (p < q)
                 << endl;
          }
        }
        return;
      };
      if (inserter.empty()) {
        add_event(rightmost(get<0>(z)), leftmost(get<2>(z)));
      } else {
        add_event(rightmost(get<0>(z)), inserter[0]);
        add_event(leftmost(get<2>(z)), inserter.back());
      }
      root = 0;
      for (int i = 0; i < inserter.size(); ++i) {
        last[inserter[i]->index] = u;
        dout << "insert " << inserter[i]->index << endl;
        inserter[i]->left = inserter[i]->right = 0;
        root = merge(root, update(inserter[i]));
      }
      root = merge(merge(get<0>(z), root), get<2>(z));
    }
    for (auto &pp : adj) {
      Vertex *u = pp.fst;
      vector<Edge *> es;
      for (auto z : pp.snd)
        es.push_back(z.snd);
      sort(all(es), [&](Edge *e, Edge *f) {
        assert(e->vertex == f->vertex);
        auto quad = [](point p) {
          for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
            if (p.x > 0 && p.y >= 0)
              return i;
          return 0;
        };
        const point p = e->twin->vertex->p - e->vertex->p;
        const point q = f->twin->vertex->p - f->vertex->p;
        if (quad(p) != quad(q))
          return quad(p) < quad(q);
        return sign(cross(p, q)) > 0;
      });
      // cout << "vertex " << u->p << endl;
      u->edge = es.back();
      for (Edge *e : es) {
        // cout << "  edge " << e << ": " << e->vertex->p << " " <<
        // e->twin->vertex->p << "; " << e->twin << endl;
        u->edge->next = e;
        u->edge->next->prev = u->edge;
        u->edge = u->edge->next;
      }
    }

    /*
        for (auto &pp: inc) {
          Vertex *u = pp.fst;
          vector<Edge*> &es = pp.snd;
          sort(all(inc[u]), [&](Edge *e, Edge *f) {
            assert(e->vertex == f->vertex);
            auto quad = [](point p) {
              for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
                if (p.x > 0 && p.y >= 0) return i;
              return 0;
            };
            const point p = e->twin->vertex->p - e->vertex->p;
            const point q = f->twin->vertex->p - f->vertex->p;
            if (quad(p) != quad(q)) return quad(p) < quad(q);
            if (sign(cross(p, q))) return sign(cross(p, q)) > 0;
            return cross(p, q) > 0;
          });
          cout << "vertex " << u->p << endl;
          u->edge = es.back();
          for (Edge *e: es) {
            cout << "  edge " << e << ": " << e->vertex->p << " " <<
       e->twin->vertex->p << "; " << e->twin << endl; u->edge->next = e;
            u->edge->next->prev = u->edge;
            u->edge = u->edge->next;
          }
        }
        */
  }
};

void AOJ1226() {
  for (int n; ~scanf("%d", &n) && n;) {
    // cout << n << endl;
    vector<vector<double>> a(4, vector<double>(n));
    for (int k = 0; k < 4; ++k)
      for (int i = 0; i < n; ++i)
        scanf("%lf", &a[k][i]);

    vector<segment> ss = {
        {{0, 0}, {0, 1}}, {{0, 1}, {1, 1}}, {{1, 1}, {1, 0}}, {{1, 0}, {0, 0}}};
    for (int i = 0; i < n; ++i) {
      ss.push_back({{a[0][i], 0}, {a[1][i], 1}});
      ss.push_back({{0, a[2][i]}, {1, a[3][i]}});
    }
    arrangement arr(ss);

    double result = 0;
    set<arrangement::Edge *> seen;
    for (auto *e : arr.edges) {
      if (seen.count(e))
        continue;
      auto *f = e;
      double area = 0;
      do {
        seen.insert(f);
        area += cross(f->vertex->p, f->twin->vertex->p);
        f = f->twin->prev;
      } while (f != e);
      result = max(result, area);
    }
    printf("%.6f\\n", result / 2);
  }
}

void AOJ2448() {
  int n;
  scanf("%d", &n);
  vector<point> ps(n);
  for (int i = 0; i < n; ++i)
    scanf("%lf %lf", &ps[i].x, &ps[i].y);
  vector<segment> ss;
  for (int i = 0; i + 1 < n; ++i)
    ss.push_back({ps[i], ps[i + 1]});
  arrangement arr(ss);

  double result = 0;
  set<arrangement::Edge *> seen;
  for (auto *e : arr.edges) {
    if (seen.count(e))
      continue;
    auto *f = e;
    double area = 0;
    do {
      seen.insert(f);
      area += cross(f->vertex->p, f->twin->vertex->p);
      f = f->twin->prev;
    } while (f != e);
    if (area > 0)
      result += area;
  }
  printf("%.12f\\n", result / 2);
}

int main() {
  // AOJ1226();
  AOJ2448();
  /*
  vector<segment> ss;
  ss.push_back({{0,0},{3,3}});
  ss.push_back({{0,0},{3,2}});
  ss.push_back({{0,1},{3,1}});
  ss.push_back({{2,0},{2,4}});
  //ss.push_back({{0,3},{3,2}});
  //ss.push_back({{1.5,0},{1.5,4}});
  arrangement arr(ss);
  */

  /*
  auto *v = arr.get({1,1});
  auto *e = v->edge;
  do {
    cout << e->vertex->p << " -- " << e->twin->vertex->p << endl;
    e = e->next;
  } while (e != v->edge);
  */
}