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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

using namespace std;
typedef long long ll;

typedef long double R;
typedef complex<R> P;

const R EPS = 1e-10;
const R PI = acos((R)(-1));

/*
 -1 -> neg
  0 -> near 0
  1 -> pos
  */
int sgn(R a) {
  if (a < -EPS)
    return -1;
  if (a > EPS)
    return 1;
  return 0;
}

int sgn(R a, R b) { return sgn(b - a); }

bool near(P a, P b) { return !sgn(abs(a - b)); }

bool lessP(const P &l, const P &r) {
  if (sgn(l.real(), r.real()))
    return l.real() < r.real();
  if (sgn(l.imag(), r.imag()))
    return l.imag() < r.imag();
  return false;
}

R cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }
R dot(P a, P b) { return a.real() * b.real() + a.imag() * b.imag(); }

R ssqrt(R d) {
  d = max<R>(0, d);
  return sqrt(d);
}

R sacos(R d) {
  d = max<R>(-1, d);
  d = min<R>(1, d);
  return acos(d);
}

R deg2rad(R x) { return x / 180 * PI; }

R rad2deg(R x) { return x / PI * 180; }

//?§???????[0, 2*PI)???
R radNorP(R x) { return fmod(fmod(x, 2 * PI) + 2 * PI, 2 * PI); }

//?§???????[-PI, PI)???
R radNorN(R x) {
  x = radNorP(x);
  if (x >= PI)
    x -= 2 * PI;
  return x;
}

/**
 * radian??§???x???[l, r]?????\\??£????????????????????\\??????
 * 0:OFF
 * 1:IN
 * 2:ON
 */
bool inR(R l, R r, R x) {
  l = radNorP(l);
  r = radNorP(r);
  x = radNorP(x);
  if (!sgn(l, x) || !sgn(r, x))
    return 2;
  if (!sgn(l, r))
    return 0;
  if (sgn(l, r) == 1) {
    if (sgn(l, x) == 1 && sgn(x, r) == 1)
      return 1;
  } else {
    if (sgn(x, r) == 1 || sgn(l, x) == 1)
      return 1;
  }
  return 0;
}

/* 1->cclock
  -1->clock
   0->on
   2->back
  -2->front
  */
int ccw(P a, P b, P c) {
  assert(!near(a, b));
  if (near(a, c) || near(b, c))
    return 0;
  int s = sgn(cross(b - a, c - a));
  if (s)
    return s;
  if (dot(b - a, c - a) < 0)
    return 2;
  if (dot(a - b, c - b) < 0)
    return -2;
  return 0;
}

struct L {
  P x, y;
  L(){};
  L(P x, P y) : x(x), y(y){};
};

P vec(const L &l) { return l.y - l.x; }

R abs(const L &l) { return abs(vec(l)); }

typedef vector<P> Pol;

struct C {
  P p;
  R r;
  C() {}
  C(P p, R r) : p(p), r(r) {}
};

P cu(Pol p, int i) {
  int s = p.size();
  return p[(i % s + s) % s];
};

// 0:P is out 1:P is on line 2:P is in
int contains(const Pol &pol, P p) {
  int in = -1;
  for (int i = 0; i < (int)pol.size(); i++) {
    P a = cu(pol, i) - p, b = cu(pol, i + 1) - p;
    if (ccw(a, b, P(0, 0)) == 0)
      return 1;
    if (imag(a) > imag(b))
      swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b)) {
      if (cross(a, b) < 0)
        in *= -1;
    }
  }
  return in + 1;
}

R distLP(const L &l, const P &p) {
  return abs(cross(vec(l), p - l.x) / abs(vec(l)));
}

//????????¨??????????°??????¢
R distSP(const L &s, const P &p) {
  P s2 = vec(s) * P(0, 1);
  if (ccw(s.x, s.x + s2, p) == 1)
    return abs(s.x - p);
  if (ccw(s.y, s.y + s2, p) == -1)
    return abs(s.y - p);
  return min(min(abs(s.x - p), abs(s.y - p)), distLP(s, p));
}

bool insSS(const L &s, const L &t) {
  int a = ccw(s.x, s.y, t.x), b = ccw(s.x, s.y, t.y);
  int c = ccw(t.x, t.y, s.x), d = ccw(t.x, t.y, s.y);
  if (a * b <= 0 && c * d <= 0)
    return true;
  return false;
}

const int MN = 55;
int n;
L l;
Pol po[MN];
R he[MN];

bool solve(R md) {
  vector<C> c;
  vector<Pol> p;
  for (int i = 0; i < n; i++) {
    R di = 0;
    if (md < he[i]) {
      di = md;
    } else {
      di = ssqrt(md * md - (md - he[i]) * (md - he[i]));
    }
    for (int j = 0; j < 4; j++) {
      c.push_back(C(po[i][j], di));
    }
    R x1 = po[i][0].real();
    R y1 = po[i][0].imag();
    R x2 = po[i][2].real();
    R y2 = po[i][2].imag();
    p.push_back(
        {P(x1 - di, y1), P(x2 + di, y1), P(x2 + di, y2), P(x1 - di, y2)});
    p.push_back(
        {P(x1, y1 - di), P(x2, y1 - di), P(x2, y2 + di), P(x1, y2 + di)});
  }
  for (C x : c) {
    if (distSP(l, x.p) < x.r)
      return false;
  }
  for (Pol x : p) {
    if (contains(x, l.x))
      return false;
    if (contains(x, l.y))
      return false;
    for (int i = 0; i < 4; i++) {
      if (insSS(l, L(cu(x, i), cu(x, i + 1))))
        return false;
    }
  }
  return true;
}

int main() {
  while (true) {
    cin >> n;
    if (!n)
      break;
    for (int i = 0; i < MN; i++) {
      po[i].clear();
    }
    R sx, sy, ex, ey;
    cin >> sx >> sy >> ex >> ey;
    l = L(P(sx, sy), P(ex, ey));
    for (int i = 0; i < n; i++) {
      R x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2 >> he[i];
      po[i].push_back(P(x1, y1));
      po[i].push_back(P(x2, y1));
      po[i].push_back(P(x2, y2));
      po[i].push_back(P(x1, y2));
    }
    R l = 0, r = 1000;
    for (int i = 0; i < 50; i++) {
      R md = (l + r) / 2;
      if (solve(md)) {
        l = md;
      } else {
        r = md;
      }
    }
    printf("%.20Lf\\n", l);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

using namespace std;
typedef long long ll;

typedef long double R;
typedef complex<R> P;

const R EPS = 1e-10;
const R PI = acos((R)(-1));

/*
 -1 -> neg
  0 -> near 0
  1 -> pos
  */
int sgn(R a) {
  if (a < -EPS)
    return -1;
  if (a > EPS)
    return 1;
  return 0;
}

int sgn(R a, R b) { return sgn(b - a); }

bool near(P a, P b) { return !sgn(abs(a - b)); }

bool lessP(const P &l, const P &r) {
  if (sgn(l.real(), r.real()))
    return l.real() < r.real();
  if (sgn(l.imag(), r.imag()))
    return l.imag() < r.imag();
  return false;
}

R cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }
R dot(P a, P b) { return a.real() * b.real() + a.imag() * b.imag(); }

R ssqrt(R d) {
  d = max<R>(0, d);
  return sqrt(d);
}

R sacos(R d) {
  d = max<R>(-1, d);
  d = min<R>(1, d);
  return acos(d);
}

R deg2rad(R x) { return x / 180 * PI; }

R rad2deg(R x) { return x / PI * 180; }

//?§???????[0, 2*PI)???
R radNorP(R x) { return fmod(fmod(x, 2 * PI) + 2 * PI, 2 * PI); }

//?§???????[-PI, PI)???
R radNorN(R x) {
  x = radNorP(x);
  if (x >= PI)
    x -= 2 * PI;
  return x;
}

/**
 * radian??§???x???[l, r]?????\\??£????????????????????\\??????
 * 0:OFF
 * 1:IN
 * 2:ON
 */
bool inR(R l, R r, R x) {
  l = radNorP(l);
  r = radNorP(r);
  x = radNorP(x);
  if (!sgn(l, x) || !sgn(r, x))
    return 2;
  if (!sgn(l, r))
    return 0;
  if (sgn(l, r) == 1) {
    if (sgn(l, x) == 1 && sgn(x, r) == 1)
      return 1;
  } else {
    if (sgn(x, r) == 1 || sgn(l, x) == 1)
      return 1;
  }
  return 0;
}

/* 1->cclock
  -1->clock
   0->on
   2->back
  -2->front
  */
int ccw(P a, P b, P c) {
  assert(!near(a, b));
  if (near(a, c) || near(b, c))
    return 0;
  int s = sgn(cross(b - a, c - a));
  if (s)
    return s;
  if (dot(b - a, c - a) < 0)
    return 2;
  if (dot(a - b, c - b) < 0)
    return -2;
  return 0;
}

struct L {
  P x, y;
  L(){};
  L(P x, P y) : x(x), y(y){};
};

P vec(const L &l) { return l.y - l.x; }

R abs(const L &l) { return abs(vec(l)); }

typedef vector<P> Pol;

struct C {
  P p;
  R r;
  C() {}
  C(P p, R r) : p(p), r(r) {}
};

P cu(Pol p, int i) {
  int s = p.size();
  return p[(i % s + s) % s];
};

// 0:P is out 1:P is on line 2:P is in
int contains(const Pol &pol, P p) {
  int in = -1;
  for (int i = 0; i < (int)pol.size(); i++) {
    P a = cu(pol, i) - p, b = cu(pol, i + 1) - p;
    if (ccw(a, b, P(0, 0)) == 0)
      return 1;
    if (imag(a) > imag(b))
      swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b)) {
      if (cross(a, b) < 0)
        in *= -1;
    }
  }
  return in + 1;
}

R distLP(const L &l, const P &p) {
  return abs(cross(vec(l), p - l.x) / abs(vec(l)));
}

//????????¨??????????°??????¢
R distSP(const L &s, const P &p) {
  P s2 = vec(s) * P(0, 1);
  if (ccw(s.x, s.x + s2, p) == 1)
    return abs(s.x - p);
  if (ccw(s.y, s.y + s2, p) == -1)
    return abs(s.y - p);
  return min(min(abs(s.x - p), abs(s.y - p)), distLP(s, p));
}

bool insSS(const L &s, const L &t) {
  int a = ccw(s.x, s.y, t.x), b = ccw(s.x, s.y, t.y);
  int c = ccw(t.x, t.y, s.x), d = ccw(t.x, t.y, s.y);
  if (a * b <= 0 && c * d <= 0)
    return true;
  return false;
}

const int MN = 55;
int n;
L l;
Pol po[MN];
R he[MN];

bool solve(R md) {
  vector<C> c;
  vector<Pol> p;
  for (int i = 0; i < n; i++) {
    R di = 0;
    if (md < he[i]) {
      di = md;
    } else {
      di = ssqrt(md * md - (md - he[i]) * (md - he[i]));
    }
    for (int j = 0; j < 4; j++) {
      c.push_back(C(po[i][j], di));
    }
    R x1 = po[i][0].real();
    R y1 = po[i][0].imag();
    R x2 = po[i][2].real();
    R y2 = po[i][2].imag();
    p.push_back(
        {P(x1 - di, y1), P(x2 + di, y1), P(x2 + di, y2), P(x1 - di, y2)});
    p.push_back(
        {P(x1, y1 - di), P(x2, y1 - di), P(x2, y2 + di), P(x1, y2 + di)});
  }
  for (C x : c) {
    if (distSP(l, x.p) < x.r)
      return false;
  }
  for (Pol x : p) {
    if (contains(x, l.x))
      return false;
    if (contains(x, l.y))
      return false;
    for (int i = 0; i < 4; i++) {
      if (insSS(l, L(cu(x, i), cu(x, i + 1))))
        return false;
    }
  }
  return true;
}

int main() {
  while (true) {
    cin >> n;
    if (!n)
      break;
    for (int i = 0; i < MN; i++) {
      po[i].clear();
    }
    R sx, sy, ex, ey;
    cin >> sx >> sy >> ex >> ey;
    l = L(P(sx, sy), P(ex, ey));
    for (int i = 0; i < n; i++) {
      R x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2 >> he[i];
      po[i].push_back(P(x1, y1));
      po[i].push_back(P(x2, y1));
      po[i].push_back(P(x2, y2));
      po[i].push_back(P(x1, y2));
    }
    R l = 0, r = 1000;
    for (int i = 0; i < 200; i++) {
      R md = (l + r) / 2;
      if (solve(md)) {
        l = md;
      } else {
        r = md;
      }
    }
    printf("%.20Lf\\n", l);
  }
  return 0;
}