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

#include <algorithm>
#include <cmath>
#include <vector>

const double INF = 1e9;
const double EPS = 1e-9;

struct Point {
  Point() : x(INF), y(INF) {}
  Point(double x, double y) : x(x), y(y) {}
  double x, y;
};
struct Compare {
  bool f;
  Compare(bool f = false) : f(f) {}
  bool operator()(const Point &lhs, const Point &rhs) const {
    return f ? lhs.y < rhs.y : lhs.x < rhs.x;
  }
};
double distance(const Point &lhs, const Point &rhs) {
  double dx = lhs.x - rhs.x;
  double dy = lhs.y - rhs.y;
  return dx * dx + dy * dy;
}

struct Result {
  double d;
  Point p1, p2;
  Result() : d(INF) {}
  Result(double d, const Point p1, const Point p2) : d(d), p1(p1), p2(p2) {}
};
bool operator<(const Result &lhs, const Result &rhs) { return lhs.d < rhs.d; }

Result closest_pair_recursion(const std::vector<Point>::const_iterator &begin,
                              const std::vector<Point>::const_iterator &end) {
  int size = end - begin;
  if (size <= 1)
    return Result();

  auto mid = begin + size / 2;
  Result r = std::min(closest_pair_recursion(begin, mid),
                      closest_pair_recursion(mid, end));

  auto left = std::lower_bound(begin, end, Point(mid->x - r.d - EPS, mid->y),
                               Compare());
  auto right =
      std::upper_bound(left, end, Point(mid->x + r.d + EPS, mid->y), Compare());
  std::vector<Point> y_sorted(left, right);
  std::sort(y_sorted.begin(), y_sorted.end(), Compare(true));

  for (auto i = y_sorted.begin(); i != y_sorted.end(); ++i) {
    for (auto j = i + 1; j != y_sorted.end(); ++j) {
      if (j->y - i->y >= r.d)
        break;
      if (distance(*i, *j) >= r.d)
        continue;
      r = Result(distance(*i, *j), *i, *j);
    }
  }
  return r;
}
Result closest_pair(std::vector<Point> point) {
  std::sort(point.begin(), point.end(), Compare());
  return closest_pair_recursion(point.begin(), point.end());
}

#include <iostream>
using namespace std;

int main() {
  int n;
  cin >> n;
  vector<Point> point(n);
  for (auto &p : point)
    cin >> p.x >> p.y;
  auto answer = closest_pair(point);
  cout << distance(answer.p1, answer.p2) << endl;
}

Error: TLE

Fixed submission:


#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;

struct Point {
  double x, y;
  Point() {}
  Point(const double x, const double y) : x(x), y(y) {}
};
bool operator<(const Point &lhs, const Point &rhs) { return lhs.x < rhs.x; }
const Point operator-(const Point &lhs, const Point &rhs) {
  return Point(lhs.x - rhs.x, lhs.y - rhs.y);
}

double distance(const Point &p1, const Point &p2) {
  Point d = p1 - p2;
  return d.x * d.x + d.y * d.y;
}

void rotate(vector<Point> &point, double angle) {
  for (auto &p : point) {
    double x = p.x * cos(angle) - p.y * sin(angle);
    double y = p.x * sin(angle) + p.y * cos(angle);
    p = Point(x, y);
  }
}

// x 座標の差が暫定解未満の点を比較 O(n^2)
// TLE 4/5 09.39s
double nearest_pair(vector<Point> point) {
  double result = distance(point[0], point[1]);
  int start = 0;
  // ランダム回転 TLE 4/5 09.41s
  rotate(point, rand());
  random_shuffle(point.begin(), point.end());
  sort(point.begin(), point.end());
  for (int i = 2; i < point.size(); ++i)
    for (int j = start; j < i; ++j) {
      if (point[i].x - point[j].x > result)
        start = j + 1;
      else
        result = min(result, distance(point[i], point[j]));
    }
  return result;
}

// 全探索 O(n^2)
// TLE 4/5 20.00 s
// int nearest_pair(vector<Point> point) {
//     int result = distance(point[0], point[1]);
//     sort(point.begin(), point.end());
//     for(int i = 2; i < point.size(); ++i) for(int j = 0; j < i; ++j) result =
//     min(result, distance(point[i], point[j])); return result;
// }

int main() {
  int n;
  cin >> n;
  vector<Point> point(n);
  for (auto &p : point)
    cin >> p.x >> p.y;
  cout << nearest_pair(point) << endl;
}