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

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef double Real;

typedef complex<Real> Point;
typedef complex<Real> Vector;
typedef pair<Point, Point> Segment;
typedef vector<Point> Polygon;

typedef pair<Real, int> P;
typedef pair<Real, Real> PR;

const Real eps = 1e-9;
const Real PI = acos(-1.0);
const Real inf = 1e9;

template <class T> bool eq(T a, T b) { return abs(a - b) < eps; }
template <class T> int sgn(T a) {
  if (eq(a, 0.0))
    return 0;
  if (a > 0)
    return 1;
  return -1;
}

Real arg(Vector v) { return atan2(v.imag(), v.real()); }

Real getDis(Real a, Real x, Real y) { return (a * x - y) / sqrt(a * a + 1.0); }

int xs[110], ys[110];
Point pts[110];
int N;

int NUM = 0;

Real get(vector<P> vec) {
  Real res = 0;
  sort(vec.begin(), vec.end());
  int cnt = 0;
  Real prev = -inf;
  for (int i = 0; i < vec.size(); i++) {
    Real x = vec[i].first;
    int y = vec[i].second;
    //		printf("(%f,%d)\\n",x,y);
    if (cnt > 0) {
      res += (x - prev);
    }
    prev = x;
    cnt += y;
  }
  //	printf("res=%f\\n",res);
  //	NUM++;
  //	if(NUM==20) exit(0);
  //	exit(0);
  return res;
}

Real calc(Real ang) {
  vector<P> vec;
  if (eq(ang, PI / 2)) {
    for (int i = 0; i < N; i++) {
      vec.push_back(P(xs[i] - 1, 1));
      vec.push_back(P(xs[i] + 1, -1));
    }
  } else {
    for (int i = 0; i < N; i++) {
      //	Real d=getDis(tan(PI/2-ang),xs[i],ys[i]);
      Real d = getDis(tan(-ang), xs[i], ys[i]);
      vec.push_back(P(d - 1, 1));
      vec.push_back(P(d + 1, -1));
    }
  }
  Real res = get(vec);
  return res;
}

vector<Real> borders;

Real normalize(Real ang) {
  if (sgn(ang) <= 0) {
    return -ang;
  }
  return abs(ang - PI);
}

Real normalize2(Real ang) {
  while (ang < 0)
    ang += PI;
  while (ang > PI)
    ang -= PI;
  return ang;
}

void solve(Real lb, Real ub);

void solve() {
  for (int i = 0; i < N; i++)
    for (int j = i + 1; j < N; j++) {
      Vector v = pts[j] - pts[i];
      Real theta = arg(v);
      theta = normalize(theta);
      borders.push_back(theta);
      if (eq(abs(v), 2.0)) {
        if (sgn(theta - PI / 2) >= 0) {
          borders.push_back(theta - PI / 2);
        } else {
          borders.push_back(theta + PI / 2);
        }
      } else {
        Real d = abs(v);
        Real phi = asin(2.0 / d);
        borders.push_back(normalize2(theta + phi));
        borders.push_back(normalize2(theta - phi));
      }
    }
  sort(borders.begin(), borders.end());
  for (int i = 0; i + 1 < borders.size(); i++) {
    solve(borders[i], borders[i + 1]);
  }
}

PR mi, Ma;

void solve(Real lb, Real ub) {
  //	printf("[%f,%f]\\n",lb,ub);
  Real x = calc(lb);
  mi = min(mi, PR(x, lb));
  Ma = max(Ma, PR(x, lb));
  x = calc(ub);
  mi = min(mi, PR(x, ub));
  Ma = max(Ma, PR(x, ub));
  if (eq(lb, ub))
    return;
#if 0
	for(int stage=0;stage<100;stage++){
		Real dif=ub-lb;
		if(dif<eps) break;
		Real ang1=lb+(dif/3.0);
		Real ang2=lb+(dif*2/3.0);
		Real val1=calc(ang1);
		Real val2=calc(ang2);
		if(val1<val2){
			lb=ang1;
		}else{
			ub=ang2;
		}
	}
	Real val=calc(lb);
	Ma=max(Ma,PR(val,lb));
#endif
  vector<P> tmp;
  Real mid = (ub + lb) / 2;
  for (int i = 0; i < N; i++) {
    Real L = sqrt(xs[i] * xs[i] + ys[i] * ys[i]);
    Real phi = atan2(ys[i], xs[i]);
    tmp.push_back(P(L * (sin(mid + phi)), i));
  }
  sort(tmp.begin(), tmp.end());
  Real coe_c = 0, coe_s = 0;
  Real c = 0;
  for (int i = 0; i < N; i++) {
    if (i == 0 || sgn(tmp[i].first - tmp[i - 1].first - 2.0) > 0) {
      c += 1.0;
      int id = tmp[i].second;
      Real L = abs(pts[id]);
      Real phi = atan2(ys[id], xs[id]);
      coe_c -= L * sin(phi);
      coe_s -= L * cos(phi);
    }
    if (i == N - 1 || sgn(tmp[i + 1].first - tmp[i].first - 2.0) > 0) {
      c += 1.0;
      int id = tmp[i].second;
      Real L = abs(pts[id]);
      Real phi = atan2(ys[id], xs[id]);
      coe_c += L * sin(phi);
      coe_s += L * cos(phi);
    }
  }
  Real A = coe_c, B = coe_s;
  Real phi = -atan2(B, -A);
  phi = normalize2(phi);
  //	printf("%f %f %f\\n",lb,phi,ub);
  if (sgn(phi - lb) >= 0 && sgn(ub - phi) >= 0) {
    Real x = calc(phi);
    Ma = max(Ma, PR(x, phi));
  }
}

void init() {
  borders.clear();
  mi = PR(inf, 0);
  Ma = PR(-inf, 0);
}

void input() {
  scanf("%d", &N);
  for (int i = 0; i < N; i++) {
    scanf("%d%d", xs + i, ys + i);
    pts[i] = Point(xs[i], ys[i]);
  }
}

int main() {
  int T = 0;
  while (true) {
    init();
    input();
    if (N == 0)
      break;
    //		if(T<60){
    //			T++;
    //			continue;
    //		}
    solve();
    if (eq(mi.second, PI))
      mi.second = 0;
    if (eq(Ma.second, PI))
      Ma.second = 0;
    printf("%.12f\\n", mi.second);
    printf("%.12f\\n", Ma.second);
    T++;
    //		if(T>=60&&T<70){
    //			fprintf(stderr,"case %d\\n",T);
    //			fprintf(stderr,"borders.size()=%d\\n",borders.size());
    //		}
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

using namespace std;

typedef double Real;

typedef complex<Real> Point;
typedef complex<Real> Vector;
typedef pair<Point, Point> Segment;
typedef vector<Point> Polygon;

typedef pair<Real, int> P;
typedef pair<Real, Real> PR;

const Real eps = 1e-9;
const Real PI = acos(-1.0);
const Real inf = 1e9;

template <class T> bool eq(T a, T b) { return abs(a - b) < eps; }
template <class T> int sgn(T a) {
  if (eq(a, 0.0))
    return 0;
  if (a > 0)
    return 1;
  return -1;
}

Real arg(Vector v) { return atan2(v.imag(), v.real()); }

Real getDis(Real a, Real x, Real y) { return (a * x - y) / sqrt(a * a + 1.0); }

int xs[110], ys[110];
Point pts[110];
int N;

int NUM = 0;

Real get(vector<P> vec) {
  Real res = 0;
  sort(vec.begin(), vec.end());
  int cnt = 0;
  Real prev = -inf;
  for (int i = 0; i < vec.size(); i++) {
    Real x = vec[i].first;
    int y = vec[i].second;
    //		printf("(%f,%d)\\n",x,y);
    if (cnt > 0) {
      res += (x - prev);
    }
    prev = x;
    cnt += y;
  }
  //	printf("res=%f\\n",res);
  //	NUM++;
  //	if(NUM==20) exit(0);
  //	exit(0);
  return res;
}

Real calc(Real ang) {
  vector<P> vec;
  if (eq(ang, PI / 2)) {
    for (int i = 0; i < N; i++) {
      vec.push_back(P(xs[i] - 1, 1));
      vec.push_back(P(xs[i] + 1, -1));
    }
  } else {
    for (int i = 0; i < N; i++) {
      //	Real d=getDis(tan(PI/2-ang),xs[i],ys[i]);
      Real d = getDis(tan(-ang), xs[i], ys[i]);
      vec.push_back(P(d - 1, 1));
      vec.push_back(P(d + 1, -1));
    }
  }
  Real res = get(vec);
  return res;
}

vector<Real> borders;

Real normalize(Real ang) {
  if (sgn(ang) <= 0) {
    return -ang;
  }
  return abs(ang - PI);
}

Real normalize2(Real ang) {
  while (ang < 0)
    ang += PI;
  while (ang > PI)
    ang -= PI;
  return ang;
}

void solve(Real lb, Real ub);

void solve() {
  for (int i = 0; i < N; i++)
    for (int j = i + 1; j < N; j++) {
      Vector v = pts[j] - pts[i];
      Real theta = arg(v);
      theta = normalize(theta);
      borders.push_back(theta);
      if (eq(abs(v), 2.0)) {
        if (sgn(theta - PI / 2) >= 0) {
          borders.push_back(theta - PI / 2);
        } else {
          borders.push_back(theta + PI / 2);
        }
      } else {
        Real d = abs(v);
        Real phi = asin(2.0 / d);
        borders.push_back(normalize2(theta + phi));
        borders.push_back(normalize2(theta - phi));
      }
    }
  sort(borders.begin(), borders.end());
  for (int i = 0; i + 1 < borders.size(); i++) {
    solve(borders[i], borders[i + 1]);
  }
}

PR mi, Ma;

void solve(Real lb, Real ub) {
  //	printf("[%f,%f]\\n",lb,ub);
  Real x = calc(lb);
  mi = min(mi, PR(x, lb));
  x = calc(ub);
  mi = min(mi, PR(x, ub));
  if (eq(lb, ub))
    return;
  for (int stage = 0; stage < 60; stage++) {
    Real dif = ub - lb;
    Real ang1 = lb + (dif / 3.0);
    Real ang2 = lb + (dif * 2 / 3.0);
    Real val1 = calc(ang1);
    Real val2 = calc(ang2);
    if (val1 < val2) {
      lb = ang1;
    } else {
      ub = ang2;
    }
  }
  Real val = calc(lb);
  Ma = max(Ma, PR(val, lb));
}

void init() {
  borders.clear();
  mi = PR(inf, 0);
  Ma = PR(-inf, 0);
}

void input() {
  scanf("%d", &N);
  for (int i = 0; i < N; i++) {
    scanf("%d%d", xs + i, ys + i);
    pts[i] = Point(xs[i], ys[i]);
  }
}

int main() {
  while (true) {
    init();
    input();
    if (N == 0)
      break;
    solve();
    printf("%.9f\\n", mi.second);
    printf("%.9f\\n", Ma.second);
  }
  return 0;
}