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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
using namespace std;
#define PII pair<int, int>
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, b, a) for (int i = (b); i >= (a); --i)
typedef long long LL;
inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-')
      f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}

const int MAXN = 300005;
const double eps = 1e-8, INF = 1e20, PI = 3.141592653589793238462;
struct list {
  int l, lt[MAXN], nt[MAXN], x[MAXN];
  void clear() {
    l = 0;
    memset(lt, 0, sizeof(lt));
  }
  void addedge(int a, int b) {
    l++;
    nt[l] = lt[a];
    lt[a] = l;
    x[l] = b;
  }
} E;
struct P {
  double x, y;
  P(double xx = 0, double yy = 0) : x(xx), y(yy) {}
  double len() const { return sqrt(x * x + y * y); }
  P operator+(const P &E) const { return P(x + E.x, y + E.y); }
  P operator-(const P &E) const { return P(x - E.x, y - E.y); }
  P operator*(const double &f) const { return P(x * f, y * f); }
  P operator/(const double &f) const { return P(x / f, y / f); }
  double operator*(const P &E) const { return x * E.y - E.x * y; }
  double operator^(const P &E) const { return x * E.x + y * E.y; }
  bool operator<(const P &E) const {
    return (x < E.x) || (x == E.x && y < E.y);
  }
} A[MAXN], B[MAXN];
double arctan(P a) {
  double ret = atan2(a.y, a.x);
  return (ret < eps ? ret + PI * 2 : ret);
}
inline double dist(P a, P b) {
  return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
inline double dot(P a, P b, P c) { return (a - c) ^ (b - c); }
inline double cross(P a, P b, P c) { return (a - c) * (b - c); }
struct line {
  double a, b, c;
  line(double aa = 0, double bb = 0, double cc = 0) : a(aa), b(bb), c(cc) {}
};
inline line get_line(P u, P v) { return line(v.y - u.y, u.x - v.x, v * u); }
P Cramer(line l1, line l2) {
  double det = l1.a * l2.b - l1.b * l2.a;
  if (fabs(det) <= eps)
    return P(INF, INF);
  return P((-l1.c * l2.b + l1.b * l2.c) / det,
           (-l1.a * l2.c + l1.c * l2.a) / det);
}
double ans;
int n, m, l, a[MAXN], b[MAXN];
int cmp(int x, int y) { return B[x] < B[y]; }
int main() {
  n = read();
  E.clear();
  l = 0;
  FOR(i, 1, n) {
    A[i].x = read();
    A[i].y = read();
  }
  FOR(i, 1, n - 1) {
    m = 0;
    FOR(j, 1, n - 1)
    if (j != i) {
      P D = Cramer(get_line(A[i], A[i + 1]), get_line(A[j], A[j + 1]));
      if ((D.x - A[i].x) * (D.x - A[i + 1].x) > eps ||
          (D.y - A[i].y) * (D.y - A[i + 1].y) > eps)
        continue;
      if ((D.x - A[j].x) * (D.x - A[j + 1].x) > eps ||
          (D.y - A[j].y) * (D.y - A[j + 1].y) > eps)
        continue;
      B[a[++m] = ++l] = D;
      FOR(k, 1, l - 1) if (dist(B[k], B[l]) <= eps) {
        l--;
        a[m] = k;
        break;
      }
      // printf("%d %d %d\\n",i,j,a[m]);
    }
    B[a[++m] = ++l] = A[i];
    FOR(k, 1, l - 1) if (dist(B[k], B[l]) <= eps) {
      l--;
      a[m] = k;
      break;
    }
    B[a[++m] = ++l] = A[i + 1];
    FOR(k, 1, l - 1) if (dist(B[k], B[l]) <= eps) {
      l--;
      a[m] = k;
      break;
    }

    sort(a + 1, a + 1 + m, cmp);
    FOR(i, 1, m - 1)
    if (dist(B[a[i]], B[a[i + 1]]) > eps)
      E.addedge(a[i], a[i + 1]), E.addedge(a[i + 1], a[i]);
  }
  // FOR(i,1,l) printf("%.3lf %.3lf %d\\n",B[i].x,B[i].y,i);
  /*FOR(i,1,l) {
          printf("%d:",i);
          for (int k=E.lt[i];k;k=E.nt[k]) printf("%d ",E.x[k]);
          printf("\\n");
  }*/
  int x = 1, y, z, s;
  double alpha = 0, tmp = 0;
  FOR(i, 2, l) if (B[i] < B[x]) x = i;
  y = E.x[E.lt[x]];
  z = s = x;
  for (int i = E.lt[x]; i; i = E.nt[i]) {
    int j = E.x[i];
    if (cross(B[j], B[y], B[x]) > eps)
      y = j;
  }
  ans = 0;
  while (1) {
    // printf("%d %d %.10lf\\n",x,y,alpha);
    ans += B[x] * B[y];
    if (y == s)
      break;
    z = x;
    x = y;
    y = E.x[E.lt[x]];
    alpha = arctan(B[y] - B[x]) - arctan(B[z] - B[x]);
    if (alpha <= eps)
      alpha += PI * 2;
    for (int i = E.lt[x]; i; i = E.nt[i]) {
      int j = E.x[i];
      tmp = arctan(B[j] - B[x]) - arctan(B[z] - B[x]);
      if (tmp <= eps)
        tmp += PI * 2;
      // printf("%d %.10lf %.10lf %.10lf %.5lf %.10lf %.10lf
      // %.5lf\\n",j,tmp,(B[j]-B[x]).x,(B[j]-B[x]).y,arctan((B[j]-B[x])),(B[z]-B[x]).x,(B[z]-B[x]).y,arctan((B[z]-B[x])));
      if (tmp < alpha) {
        alpha = tmp;
        y = j;
      }
    }
  }
  printf("%.10lf\\n", fabs(ans) / 2);

  return 0;
}

/*
5
1 1
2 3
3 4
2 5
4 2

*/

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#define eps 1.0e-8
#define sgn(f) ((f) < (-eps) ? -1 : ((f) > eps))
using namespace std;
typedef long double df;
const double pi = acos(-1.0);
struct point {
  df x, y;
  point(df _x = 0, df _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*(df p) { return point(x * p, y * p); }
  point operator/(df 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 {
    return (sgn(x - a.x) < 0) || ((sgn(x - a.x) == 0) && (sgn(y - a.y) < 0));
  }
};
typedef point Vector;
df dmult(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }
df xmult(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }
df xmult(point a, point b, point o) {
  return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}
df dis2(point a, point b) {
  return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
df angle(Vector v) { return atan2(v.y, v.x); }
df RelativeAngle(Vector v, Vector u) {
  df c = dmult(v, u) / sqrt((v.x * v.x + v.y * v.y) * (u.x * u.x + u.y * u.y));
  df angle = acos(c);
  if (sgn(xmult(v, u)) < 0)
    angle = 2 * pi - angle;
  return angle;
}
bool check(point sa, point sb, point ta, point tb) {
  if (sgn(xmult(sa, sb, ta)) * sgn(xmult(sa, sb, tb)) != -1)
    return false;
  if (sgn(xmult(ta, tb, sa)) * sgn(xmult(ta, tb, sb)) != -1)
    return false;
  return true;
}
bool isonsegment(point a, point b, point c) {
  if (sgn(xmult(a, b, c)))
    return false;
  if (sgn(dmult(a - c, b - c)) > 0)
    return false;
  return true;
}
int GetLineIntersection(point p, Vector v, point q, Vector w, point &ans) {
  /*if(sgn(xmult(v,w))==0)
  {
      if(sgn(xmult(p-q,w))==0) return 2;
      else return 0;
  }*/
  ans = p + v * xmult(w, p - q) / xmult(v, w);
  return 1;
}

point tp[6666];
int N, cnt, head[6666];
vector<pair<int, int>> g;
struct edge {
  int to, nxt;
  bool vis;
  edge() {}
  edge(int a, int b) {
    to = a;
    nxt = b;
    vis = false;
  }
} e[233333];
void addedge(int a, int b) {
  e[cnt] = edge(b, head[a]);
  head[a] = cnt++;
}
void init() {
  N = 0;
  cnt = 0;
  g.clear();
  memset(head, -1, sizeof(head));
}
struct node {
  df v;
  int id;
  node() {}
  node(df a, int b) {
    v = a;
    id = b;
  }
  bool operator<(const node &t) const { return sgn(v - t.v) < 0; }
};
void FindBorder(int n, point *p, vector<point> &ans) {
  // 初始化
  ans.clear();
  init();

  // 求点去重
  Vector vt[233];
  for (int i = 0; i < n; ++i)
    vt[i] = p[i + 1] - p[i];
  tp[N++] = p[n];
  for (int i = 0; i < n; ++i) {
    tp[N++] = p[i];
    for (int j = i + 1; j < n; ++j) {
      if (check(p[i], p[i + 1], p[j], p[j + 1])) {
        GetLineIntersection(p[i], vt[i], p[j], vt[j], tp[N]);
        N++;
      }
    }
  }
  sort(tp, tp + N);
  N = unique(tp, tp + N) - tp;

  // 建?去重
  for (int i = 0; i < n; ++i) {
    node q[6666];
    int M = 0;
    for (int j = 0; j < N; ++j)
      if (isonsegment(p[i], p[i + 1], tp[j]))
        q[M++] = node(dis2(tp[j], p[i]), j);
    sort(q, q + M);
    for (int j = 0; j < M - 1; ++j) {
      g.push_back(make_pair(q[j].id, q[j + 1].id));
      g.push_back(make_pair(q[j + 1].id, q[j].id));
    }
  }
  sort(g.begin(), g.end());
  g.erase(unique(g.begin(), g.end()), g.end());
  for (int i = 0; i < g.size(); ++i)
    addedge(g[i].first, g[i].second);

  //?似于卷包裹法求?廓
  ans.push_back(tp[0]);
  int from = 0, to = e[head[0]].to;
  for (int i = head[0]; i != -1; i = e[i].nxt) {
    int v = e[i].to;
    if (sgn(angle(tp[v] - tp[0]) - angle(tp[to] - tp[0])) < 0)
      to = v;
  }
  while (1) {
    int nto = from, idx = 0, fromidx = 0;
    df angle = 1e15;
    for (int i = head[to]; i != -1; i = e[i].nxt) {
      int v = e[i].to;
      if (v == from) {
        fromidx = i;
        continue;
      }
      if (e[i].vis)
        continue;
      df nangle = RelativeAngle(tp[from] - tp[to], tp[v] - tp[to]);
      if (sgn(nangle - angle) < 0) {
        nto = v;
        angle = nangle;
        idx = i;
      }
    }
    if (nto == from)
      idx = fromidx;
    e[idx].vis = true;
    ans.push_back(tp[to]);
    from = to;
    to = nto;
    if (from == 0)
      break;
  };
}
int main() {
  int a = sizeof(long double);
  int b = sizeof(double);
  if (a > b)
    while (1)
      ;
  int n;
  point s[105];
  vector<point> q;
  df area = 0;

  scanf("%d", &n);
  n--;
  for (int i = 0; i <= n; ++i) {
    double x, y;
    scanf("%lf%lf", &x, &y);
    s[i].x = x;
    s[i].y = y;
  }
  FindBorder(n, s, q);
  for (int i = 0; i < q.size() - 1; ++i)
    area += xmult(q[i], q[i + 1]);
  area *= 0.5;
  if (sgn(area) <= 0)
    area = 0;
  printf("%.10f\\n", area);
  return 0;
}