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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

struct Info {
  bool operator<(const struct Info &arg) const {
    if (x != arg.x) {
      return x < arg.x;
    } else {
      return y < arg.y;
    }
  }
  double x, y, r;
};

int N;
Info info[100001];

bool compare_y(Info left, Info right) { return left.y < right.y; }

double calc_dist(int a, int b) {
  return sqrt((info[a].x - info[b].x) * (info[a].x - info[b].x) +
              (info[a].y - info[b].y) * (info[a].y - info[b].y)) -
         (info[a].r + info[b].r);
}

double calc_y_dist(int a, int b) {
  return (info[b].y - info[b].r) - (info[a].y + info[a].r);
}

double closest_pair(Info *array, int tmp_N) {
  if (tmp_N <= 1)
    return DBL_MAX;

  int mid = tmp_N / 2;

  double x = array[mid].x;
  double dist =
      min(closest_pair(array, mid), closest_pair(array + mid, tmp_N - mid));
  inplace_merge(array, array + mid, array + tmp_N, compare_y);

  vector<int> V;

  int left, right, m, search_left;

  for (int i = 0; i < tmp_N; i++) {

    for (int k = 0; k < min((int)V.size(), 2); k++) {
      dist = min(dist, calc_dist(V[V.size() - 1 - k], i));
    }

    V.push_back(i);
  }
  return dist;
}

void func() {

  for (int i = 0; i < N; i++) {
    scanf("%lf %lf %lf", &info[i].r, &info[i].x, &info[i].y);
  }
  sort(info, info + N);

  printf("%.10lf\\n", closest_pair(info, N));
}

int main() {

  while (true) {
    scanf("%d", &N);
    if (N == 0)
      break;

    func();
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string>
#include <time.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

struct Info {
  bool operator<(const struct Info &arg) const {
    if (x != arg.x) {
      return x < arg.x;
    } else {
      return y < arg.y;
    }
  }
  double x, y, r;
};

int N;
double max_r;
Info info[100001];

bool compare_y(Info left, Info right) { // 順序付け関数

  return left.y < right.y;
}

bool is_OK(int index, double x, double dist) {
  if (info[index].x < x) { // 基準線より中心が左
    if (info[index].x + info[index].r + dist <
        x - 2 * max_r) { // ★★中心線より反対側に円がはみ出す場合がある
      return false;
    }

  } else { // 基準線より中心が右
    if (info[index].x - info[index].r - dist > x + 2 * max_r) {
      return false;
    }
  }
  return true;
}

double calc_dist(int a, int b) {
  return sqrt((info[a].x - info[b].x) * (info[a].x - info[b].x) +
              (info[a].y - info[b].y) * (info[a].y - info[b].y)) -
         (info[a].r + info[b].r);
}

double closest_pair(Info *array, int tmp_N) {
  if (tmp_N <= 1)
    return DBL_MAX;

  int mid = tmp_N / 2; // 中央のインデックス

  double x = array[mid].x; // 基準線
  double r = array[mid].r; // 半径
  double dist =
      min(closest_pair(array, mid),
          closest_pair(array + mid,
                       tmp_N - mid)); // 集合を2分割し、再帰的に最小距離を求める
  inplace_merge(array, array + mid, array + tmp_N,
                compare_y); // 2つのソート済の範囲をマージ

  vector<int> V; // ★★再帰毎にメモリを確保(indexをpush)★★

  int left, right, m, search_left;

  for (int i = 0; i < tmp_N; i++) {
    // if(!is_OK(i,x,dist))continue;
    // //異なる領域間での、新最小値を作り得ない場合は無視
    if (fabs(info[i].x - x) - (info[i].r + r) >= dist)
      continue;

    left = 0, right = V.size() - 1, m = (left + right) / 2;
    search_left = V.size() - 1;

    // Vはy座標の昇順にpushされている→自分よりy座標が小さいもののみが入っている
    while (left <= right) {
      if ((info[i].y - info[i].r) - (info[m].y + info[m].r) <
          dist) { // y座標の差がdist未満の場合
        search_left = m;
        right = m - 1; // より左へ
      } else {
        left = m + 1;
      }
      m = (left + right) / 2;
    }

    // for(int k = search_left; k < V.size(); k++){
    for (int k = 0; k < V.size(); k++) {
      dist = min(dist, calc_dist(V[k], i));
    }
    V.push_back(i); // 可能性あり集合に、iを追加
  }
  return dist;
}

void func() {

  max_r = 0;

  for (int i = 0; i < N; i++) {
    scanf("%lf %lf %lf", &info[i].r, &info[i].x, &info[i].y);
    max_r = max(max_r, info[i].r);
  }
  sort(info, info + N);

  printf("%.10lf\\n", closest_pair(info, N));
}

int main() {

  while (true) {
    scanf("%d", &N);
    if (N == 0)
      break;

    func();
  }

  return 0;
}