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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;
typedef complex<double> P;
namespace std {
bool operator<(const P &a, const P &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std
double cross(const P &a, const P &b) { return imag(conj(a) * b); }
double dot(const P &a, const P &b) { return real(conj(a) * b); }
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a);
    push_back(b);
  }
};
typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i + 1) % P.size()]
struct C {
  P p;
  double r;
  C(const P &p, double r) : p(p), r(r) {}
  C() {}
};

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0)
    return +1; // counter clockwise
  if (cross(b, c) < 0)
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;
}

P projection(const L &l, const P &p) {
  double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}

vector<P> crosspointLC(const L &l, const C &c) {
  vector<P> ret;
  P center = projection(l, c.p);
  double d = abs(center - c.p);
  double t = sqrt(c.r * c.r - d * d);
  if (isnan(t)) {
    return ret;
  }
  P vect = (l[1] - l[0]);
  vect /= abs(vect);
  ret.push_back(center - vect * t);
  if (t > EPS) {
    ret.push_back(center + vect * t);
  }
  return ret;
}

bool contain(const C &c1, const C &c2) {
  double d = abs(c1.p - c2.p);
  return c1.r - c2.r - d > -EPS;
}
vector<P> crosspointCC(const C &c1, const C &c2) {
  vector<P> ret;
  double d = abs(c1.p - c2.p);
  if (max(c1.r, c2.r) - min(c1.r, c2.r) - d > -EPS) {
    return ret;
  }
  double x = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  P start = c1.p + (c2.p - c1.p) / d * x;
  P vect = (c1.p - c2.p) * P(0.0, 1.0);
  return crosspointLC(L(start, start + vect), c1);
}

double angle(
    const P &a,
    const P &
        b) { // ツベツクツトツδ仰つつゥツづァツづ敖つスツベツクツトツδ仰つつづ個角ツ度ツづ個計ツ算[0,2pi]
  double ret = arg(b) - arg(a);
  return (ret >= 0) ? ret : ret + 2 * PI;
}
typedef pair<double, double> pdd;

double func(C c, const vector<pdd> &v) {
  if (v.size() == 0)
    return 0;
  double x, y;
  double ans = 0;
  REP(i, v.size()) {
    double a = v[i].first, b = v[i].second;
    if (i == 0) {
      x = a;
      y = b;
      continue;
    }
    if (y >= a) {
      y = max(y, b);
    } else {
      ans += c.r * (y - x);
      x = a;
      y = b;
    }
  }
  ans += c.r * (y - x);
  return ans;
}

int main() {
  int n;
  while (cin >> n, n) {
    C c[n];
    REP(i, n) {
      double x, y, r;
      cin >> x >> y >> r;
      c[i] = C(P(x, y), r);
    }
    vector<pdd> ngang[n];
    REP(i, n) {
      // cout << i << endl;
      REP(j, n) {
        if (i == j)
          continue;
        double d = abs(c[i].p - c[j].p);
        if (c[j].r - c[i].r - d > -EPS) {
          ngang[i].push_back(pdd(0, 2 * PI));
          continue;
        }
        if (c[i].r - c[j].r - d > -EPS)
          continue;
        if (d + EPS >= c[i].r + c[j].r)
          continue;
        vector<P> vp = crosspointCC(c[i], c[j]);
        assert(vp.size() == 2);
        if (vp.size() != 2)
          continue;
        // cout << vp[0] << " " << vp[1] << endl;
        double a1 = arg(vp[1] - c[i].p);
        double a2 = arg(vp[0] - c[i].p);
        if (a1 < 0)
          a1 += 2 * PI;
        if (a2 < 0)
          a2 += 2 * PI;
        if (a2 - a1 < 0) {
          ngang[i].push_back(pdd(a1, 2 * PI));
          ngang[i].push_back(pdd(0, a2));
        } else {
          ngang[i].push_back(pdd(a1, a2));
        }
      }
    }
    double ans = 0;
    REP(i, n) {
      // cout << "i = " << i << endl;
      // cout << ngang[i].size() << endl;
      sort(ALL(ngang[i]));
      double tmp = func(c[i], ngang[i]);
      ans += c[i].r * 2 * PI - tmp;
    }

    printf("%.10f\\n", ans);
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;
typedef complex<double> P;
namespace std {
bool operator<(const P &a, const P &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std
double cross(const P &a, const P &b) { return imag(conj(a) * b); }
double dot(const P &a, const P &b) { return real(conj(a) * b); }
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a);
    push_back(b);
  }
};
typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i + 1) % P.size()]
struct C {
  P p;
  double r;
  C(const P &p, double r) : p(p), r(r) {}
  C() {}
};

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0)
    return +1; // counter clockwise
  if (cross(b, c) < 0)
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;
}

P projection(const L &l, const P &p) {
  double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}

vector<P> crosspointLC(const L &l, const C &c) {
  vector<P> ret;
  P center = projection(l, c.p);
  double d = abs(center - c.p);
  double t = sqrt(c.r * c.r - d * d);
  if (isnan(t)) {
    return ret;
  }
  P vect = (l[1] - l[0]);
  vect /= abs(vect);
  ret.push_back(center - vect * t);
  if (t > EPS) {
    ret.push_back(center + vect * t);
  }
  return ret;
}

bool contain(const C &c1, const C &c2) {
  double d = abs(c1.p - c2.p);
  return c1.r - c2.r - d > -EPS;
}
vector<P> crosspointCC(const C &c1, const C &c2) {
  vector<P> ret;
  double d = abs(c1.p - c2.p);
  if (max(c1.r, c2.r) - min(c1.r, c2.r) - d > -EPS) {
    return ret;
  }
  double x = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  P start = c1.p + (c2.p - c1.p) / d * x;
  P vect = (c1.p - c2.p) * P(0.0, 1.0);
  return crosspointLC(L(start, start + vect), c1);
}

double angle(
    const P &a,
    const P &
        b) { // ツベツクツトツδ仰つつゥツづァツづ敖つスツベツクツトツδ仰つつづ個角ツ度ツづ個計ツ算[0,2pi]
  double ret = arg(b) - arg(a);
  return (ret >= 0) ? ret : ret + 2 * PI;
}
typedef pair<double, double> pdd;

double func(C c, const vector<pdd> &v) {
  if (v.size() == 0)
    return 0;
  double x, y;
  double ans = 0;
  REP(i, v.size()) {
    double a = v[i].first, b = v[i].second;
    if (i == 0) {
      x = a;
      y = b;
      continue;
    }
    if (y >= a) {
      y = max(y, b);
    } else {
      ans += c.r * (y - x);
      x = a;
      y = b;
    }
  }
  ans += c.r * (y - x);
  return ans;
}

int main() {
  int n;
  while (cin >> n, n) {
    C c[n];
    REP(i, n) {
      int x, y, r;
      cin >> x >> y >> r;
      c[i] = C(P(x, y), r);
    }
    vector<pdd> ngang[n];
    REP(i, n) {
      // cout << i << endl;
      REP(j, n) {
        if (i == j)
          continue;
        double d = abs(c[i].p - c[j].p);
        if (c[j].r - c[i].r - d > -EPS) {
          ngang[i].push_back(pdd(0, 2 * PI));
          continue;
        }
        if (c[i].r - c[j].r - d > -EPS)
          continue;
        if (d + EPS >= c[i].r + c[j].r)
          continue;
        vector<P> vp = crosspointCC(c[i], c[j]);
        assert(vp.size() == 2);
        if (vp.size() != 2)
          continue;
        // cout << vp[0] << " " << vp[1] << endl;
        double a1 = arg(vp[1] - c[i].p);
        double a2 = arg(vp[0] - c[i].p);
        if (a1 < 0)
          a1 += 2 * PI;
        if (a2 < 0)
          a2 += 2 * PI;
        if (a2 - a1 < 0) {
          ngang[i].push_back(pdd(a1, 2 * PI));
          ngang[i].push_back(pdd(0, a2));
        } else {
          ngang[i].push_back(pdd(a1, a2));
        }
      }
    }
    double ans = 0;
    REP(i, n) {
      // cout << "i = " << i << endl;
      // cout << ngang[i].size() << endl;
      sort(ALL(ngang[i]));
      double tmp = func(c[i], ngang[i]);
      ans += c[i].r * 2 * PI - tmp;
    }

    printf("%.10f\\n", ans);
  }
}