Problem p01562 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cmath>
#include <cstdio>
#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;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
#define eps 1.0e-9
#define sgn(f) ((f) < (-eps) ? -1 : ((f) > eps))
using namespace std;
const double pi = acos(-1.0);
int n;
struct point {
  double x, y;
  point(double _x = 0, double _y = 0) : x(_x), y(_y){};
  point operator+(point a) { return point(x + a.x, y + a.y); }
  point operator-(point a) { return point(x - a.x, y - a.y); }
  point operator*(double p) { return point(x * p, y * p); }
  point operator/(double p) { return point(x / p, y / p); }
  bool operator==(point a) { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0; }
  bool operator<(const point a) const {
    if (sgn(x - a.x) != 0)
      return sgn(x - a.x) < 0;
    else
      return sgn(y - a.y) < 0;
  }
};
typedef point Vector;
double dmult(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }
double xmult(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }
double Length(Vector a) { return sqrt(dmult(a, a)); }
point GetLineIntersection(point p, Vector v, point q, Vector w) {
  Vector u = p - q;
  if (sgn(xmult(v, w)) == 0)
    while (1)
      ;
  double t = xmult(w, u) / xmult(v, w);
  return p + v * t;
}
bool SegmentProperIntersection(point a1, point a2, point b1, point b2) {
  double c1 = xmult(a2 - a1, b1 - a1);
  double c2 = xmult(a2 - a1, b2 - a1);
  double c3 = xmult(b2 - b1, a1 - b1);
  double c4 = xmult(b2 - b1, a2 - b1);
  return sgn(c1) * sgn(c2) < 0 && sgn(c3) * sgn(c4) < 0;
}
bool OnSegment(point p, point a1, point a2) {
  return sgn(xmult(a1 - p, a2 - p)) == 0 && sgn(dmult(a1 - p, a2 - p)) < 0;
}
point ans[233333], z[233333];
double x[233333];
void FindBorder(point *p, int n) {
  if (n == 0)
    while (1)
      ;
  int num, a, min1 = 0;
  for (int q = 0; q < n; ++q)
    if (p[q] < p[min1])
      min1 = q;
  ans[0] = p[min1];
  double s = -pi;
  num = 1;
  for (int idx = 0;; idx++) {
    a = 0;
    for (int q = 0; q < n; ++q) {
      if (p[q] == ans[num - 1]) {
        z[a] = p[(q + 1) % n];
        x[a] = atan2(-p[q].y + z[a].y, -p[q].x + z[a].x) - s - 2 * pi;
        while (sgn(x[a]) <= 0)
          x[a] += 2 * pi;
        a++;

        z[a] = p[(q + n - 1) % n];
        x[a] = atan2(-p[q].y + z[a].y, -p[q].x + z[a].x) - s - 2 * pi;
        while (sgn(x[a]) <= 0)
          x[a] += 2 * pi;
        a++;
      }
    }
    for (int q = 0; q < n; ++q) {
      if (OnSegment(ans[num - 1], p[q], p[q + 1])) {
        z[a] = p[q + 1];
        x[a] = atan2(-ans[num - 1].y + z[a].y, -ans[num - 1].x + z[a].x) - s -
               2 * pi;
        while (sgn(x[a]) <= 0)
          x[a] += 2 * pi;
        a++;
        z[a] = p[q];
        x[a] = atan2(-ans[num - 1].y + z[a].y, -ans[num - 1].x + z[a].x) - s -
               2 * pi;
        while (sgn(x[a]) <= 0)
          x[a] += 2 * pi;
        a++;
      }
    }
    int mi = 0;
    for (int q = 0; q < a; ++q)
      if (x[q] < x[mi])
        mi = q;
    double ma = 1e20;
    point f = z[mi], g;
    for (int q = 0; q < n; ++q) {
      if (SegmentProperIntersection(z[mi], ans[num - 1], p[q], p[q + 1])) {
        g = GetLineIntersection(z[mi], z[mi] - ans[num - 1], p[q],
                                p[q] - p[q + 1]);
        if (Length(g - ans[num - 1]) < ma) {
          ma = Length(g - ans[num - 1]);
          f = g;
        }
      }
    }
    ans[num] = f;
    s = atan2(ans[num - 1].y - ans[num].y, ans[num - 1].x - ans[num].x);
    num++;
    if (num > 233333)
      while (1)
        ;
    if (ans[num - 1] == ans[0])
      break;
  }
  double S = 0;
  for (int q = 0; q < num - 1; ++q)
    S += xmult(ans[q], ans[q + 1]);
  if (sgn(S) < 0)
    S = -S;
  printf("%.10f\\n", S * 0.5);
}
point p[233333];
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; ++i)
    scanf("%lf%lf", &p[i].x, &p[i].y);
  if (p[n - 1] == p[0])
    n--;
  else {
    for (int i = 0; i < n - 1; ++i)
      p[n + i] = p[n - i - 2];
    n = 2 * n - 2;
  }
  FindBorder(p, n);
  return 0;
}