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

#include <cmath>
#include <iostream>
#include <limits>
#include <set>
#include <utility>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

namespace libcomp {
namespace geometry {

const double EPS = 1e-9;

bool tolerant_eq(double a, double b) { return abs(a - b) < EPS; }

struct Point {
  double x;
  double y;

  explicit Point(const double &x = 0.0, const double &y = 0.0) : x(x), y(y) {}

  static Point invalid() {
    double qnan = numeric_limits<double>::quiet_NaN();
    return Point(qnan, qnan);
  }
  bool is_valid() const { return !(isnan(x) || isnan(y)); }

  Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
  Point &operator+=(const Point &p) { return *this = *this + p; }
  Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
  Point &operator-=(const Point &p) { return *this = *this - p; }
  Point operator*(double s) const { return Point(x * s, y * s); }
  Point &operator*=(double s) { return *this = *this * s; }
  Point operator/(double s) const { return Point(x / s, y / s); }
  Point &operator/=(double s) { return *this = *this / s; }

  bool operator==(const Point &p) const { return x == p.x && y == p.y; }
  bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
  bool operator<(const Point &p) const {
    return (x == p.x) ? (y < p.y) : (x < p.x);
  }
};

Point operator*(double s, const Point &p) { return p * s; }

bool tolerant_eq(const Point &a, const Point &b) {
  return tolerant_eq(a.x, b.x) && tolerant_eq(a.y, b.y);
}

double abs(const Point &p) { return sqrt(p.x * p.x + p.y * p.y); }
double norm(const Point &p) { return p.x * p.x + p.y * p.y; }
Point unit(const Point &p) { return p / abs(p); }
Point ortho(const Point &p) { return Point(-p.y, p.x); }
double cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
int ccw(const Point &a, const Point &b, const Point &c) {
  Point d = b - a, e = c - a;
  if (cross(d, e) > 0.0) {
    return 1;
  }
  if (cross(d, e) < 0.0) {
    return -1;
  }
  if (dot(d, e) < 0.0) {
    return 2;
  }
  if (abs(d) < abs(e)) {
    return -2;
  }
  return 0;
}

struct Line {
  Point a;
  Point b;

  explicit Line(const Point &a = Point(), const Point &b = Point())
      : a(a), b(b) {}

  static Line invalid() {
    Point inv = Point::invalid();
    return Line(inv, inv);
  }
  bool is_valid() const { return a.is_valid() && b.is_valid(); }

  bool operator<(const Line &l) const {
    return (a == l.a) ? (b < l.b) : (a < l.a);
  }
};

bool tolerant_eq(const Line &a, const Line &b) {
  return ::std::abs(cross(a.b - a.a, b.a - a.a)) < EPS;
}

Point projection(const Line &l, const Point &p) {
  double t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
  return l.a + t * (l.b - l.a);
}

Point reflection(const Line &l, const Point &p) {
  return p + 2.0 * (projection(l, p) - p);
}

} // namespace geometry
} // namespace libcomp

using namespace libcomp::geometry;
typedef pair<int, int> pii;

inline ll pow2(ll x) { return x * x; }

int main() {
  ios_base::sync_with_stdio(false);
  int n;
  cin >> n;
  vector<Point> p(n);
  set<pii> ps;
  int xsum = 0, ysum = 0;
  for (int i = 0; i < n; ++i) {
    int x, y;
    cin >> x >> y;
    p[i] = Point(x, y);
    ps.insert(pii(x, y));
    xsum += x;
    ysum += y;
  }
  const Point c(static_cast<double>(xsum) / n, static_cast<double>(ysum) / n);
  bool answer = false;
  if (n % 2 == 0) {
    for (int i = 0; i < n; ++i) {
      if (tolerant_eq(p[i], c)) {
        continue;
      }
      const Line l(p[i], c);
      bool accept = true;
      int count = 0;
      for (int j = 0; accept && j < n; ++j) {
        const Point a = p[j];
        const Point b = reflection(l, a);
        if (tolerant_eq(a, b) && ++count > 2) {
          accept = false;
        }
        const int ibx = static_cast<int>(floor(b.x + 0.5));
        const int iby = static_cast<int>(floor(b.y + 0.5));
        const Point d(ibx, iby);
        if (!tolerant_eq(b, d)) {
          accept = false;
        }
        if (ps.find(pii(ibx, iby)) == ps.end()) {
          accept = false;
        }
      }
      if (accept) {
        answer = true;
        break;
      }
    }
  }
  for (int i = 0; !answer && i < 4; ++i) {
    for (int j = i + 1; !answer && j < n; ++j) {
      const Point q = projection(Line(p[i], p[j]), c);
      if (tolerant_eq(q, c)) {
        continue;
      }
      const Line l((p[i] + p[j]) / 2, c);
      bool accept = true;
      int count = 0;
      for (int k = 0; accept && k < n; ++k) {
        const Point a = p[k];
        const Point b = reflection(l, a);
        if (tolerant_eq(a, b) && ++count > n % 2) {
          accept = false;
        }
        const int ibx = static_cast<int>(floor(b.x + 0.5));
        const int iby = static_cast<int>(floor(b.y + 0.5));
        const Point d(ibx, iby);
        if (!tolerant_eq(b, d)) {
          accept = false;
        }
        if (ps.find(pii(ibx, iby)) == ps.end()) {
          accept = false;
        }
      }
      if (accept) {
        answer = true;
      }
    }
  }
  cout << (answer ? "Yes" : "No") << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <cmath>
#include <iostream>
#include <limits>
#include <set>
#include <utility>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

namespace libcomp {
namespace geometry {

const double EPS = 1e-9;

bool tolerant_eq(double a, double b) { return abs(a - b) < EPS; }

struct Point {
  double x;
  double y;

  explicit Point(const double &x = 0.0, const double &y = 0.0) : x(x), y(y) {}

  static Point invalid() {
    double qnan = numeric_limits<double>::quiet_NaN();
    return Point(qnan, qnan);
  }
  bool is_valid() const { return !(isnan(x) || isnan(y)); }

  Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
  Point &operator+=(const Point &p) { return *this = *this + p; }
  Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
  Point &operator-=(const Point &p) { return *this = *this - p; }
  Point operator*(double s) const { return Point(x * s, y * s); }
  Point &operator*=(double s) { return *this = *this * s; }
  Point operator/(double s) const { return Point(x / s, y / s); }
  Point &operator/=(double s) { return *this = *this / s; }

  bool operator==(const Point &p) const { return x == p.x && y == p.y; }
  bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
  bool operator<(const Point &p) const {
    return (x == p.x) ? (y < p.y) : (x < p.x);
  }
};

Point operator*(double s, const Point &p) { return p * s; }

bool tolerant_eq(const Point &a, const Point &b) {
  return tolerant_eq(a.x, b.x) && tolerant_eq(a.y, b.y);
}

double abs(const Point &p) { return sqrt(p.x * p.x + p.y * p.y); }
double norm(const Point &p) { return p.x * p.x + p.y * p.y; }
Point unit(const Point &p) { return p / abs(p); }
Point ortho(const Point &p) { return Point(-p.y, p.x); }
double cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
int ccw(const Point &a, const Point &b, const Point &c) {
  Point d = b - a, e = c - a;
  if (cross(d, e) > 0.0) {
    return 1;
  }
  if (cross(d, e) < 0.0) {
    return -1;
  }
  if (dot(d, e) < 0.0) {
    return 2;
  }
  if (abs(d) < abs(e)) {
    return -2;
  }
  return 0;
}

struct Line {
  Point a;
  Point b;

  explicit Line(const Point &a = Point(), const Point &b = Point())
      : a(a), b(b) {}

  static Line invalid() {
    Point inv = Point::invalid();
    return Line(inv, inv);
  }
  bool is_valid() const { return a.is_valid() && b.is_valid(); }

  bool operator<(const Line &l) const {
    return (a == l.a) ? (b < l.b) : (a < l.a);
  }
};

bool tolerant_eq(const Line &a, const Line &b) {
  return ::std::abs(cross(a.b - a.a, b.a - a.a)) < EPS;
}

Point projection(const Line &l, const Point &p) {
  double t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
  return l.a + t * (l.b - l.a);
}

Point reflection(const Line &l, const Point &p) {
  return p + 2.0 * (projection(l, p) - p);
}

} // namespace geometry
} // namespace libcomp

using namespace libcomp::geometry;
typedef pair<int, int> pii;

inline ll pow2(ll x) { return x * x; }

int main() {
  ios_base::sync_with_stdio(false);
  int n;
  cin >> n;
  vector<Point> p(n);
  set<pii> ps;
  int xsum = 0, ysum = 0;
  for (int i = 0; i < n; ++i) {
    int x, y;
    cin >> x >> y;
    p[i] = Point(x, y);
    ps.insert(pii(x, y));
    xsum += x;
    ysum += y;
  }
  const Point c(static_cast<double>(xsum) / n, static_cast<double>(ysum) / n);
  bool answer = false;
  if (n % 2 == 0) {
    for (int i = 0; i < n; ++i) {
      if (tolerant_eq(p[i], c)) {
        continue;
      }
      const Line l(p[i], c);
      bool accept = true;
      int count = 0;
      for (int j = 0; accept && j < n; ++j) {
        const Point a = p[j];
        const Point b = reflection(l, a);
        if (tolerant_eq(a, b) && ++count > 2) {
          accept = false;
        }
        const int ibx = static_cast<int>(floor(b.x + 0.5));
        const int iby = static_cast<int>(floor(b.y + 0.5));
        const Point d(ibx, iby);
        if (!tolerant_eq(b, d)) {
          accept = false;
        }
        if (ps.find(pii(ibx, iby)) == ps.end()) {
          accept = false;
        }
      }
      if (accept) {
        answer = true;
        break;
      }
    }
  }
  for (int i = 0; !answer && i < n; ++i) {
    for (int j = i + 1; !answer && j < n; ++j) {
      const Point q = projection(Line(p[i], p[j]), c);
      if (tolerant_eq(q, c)) {
        continue;
      }
      const Line l((p[i] + p[j]) / 2, c);
      bool accept = true;
      int count = 0;
      for (int k = 0; accept && k < n; ++k) {
        const Point a = p[k];
        const Point b = reflection(l, a);
        if (tolerant_eq(a, b) && ++count > n % 2) {
          accept = false;
        }
        const int ibx = static_cast<int>(floor(b.x + 0.5));
        const int iby = static_cast<int>(floor(b.y + 0.5));
        const Point d(ibx, iby);
        if (!tolerant_eq(b, d)) {
          accept = false;
        }
        if (ps.find(pii(ibx, iby)) == ps.end()) {
          accept = false;
        }
      }
      if (accept) {
        answer = true;
      }
    }
  }
  cout << (answer ? "Yes" : "No") << endl;
  return 0;
}