Problem p00508 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>

#define FOR(i, a, b) for (int i = a; i < b; i++)
#define REP(i, b) FOR(i, 0, b)
#define MP make_pair
#define PB push_back

using namespace std;

int read() {
  int i;
  scanf("%d", &i);
  return i;
}

const int Nmax = 500000;
int n;

const double eps = 1e-9;
const double inf = 1e10;
double lineY;

struct Pos {
  double x, y;
  void dbgOut() const { cout << "x " << x << " y " << y << endl; }
} sites[Nmax];

vector<int> graph[Nmax];

void AddEdge(int a, int b) {
  if (0 <= a && a < Nmax && 0 <= b && b < Nmax) {
    graph[a].PB(b);
    graph[b].PB(a);
  }
}

inline double Square(double x) { return x * x; }

inline double Cross(const Pos &a, const Pos &b) {
  return a.x * b.y - a.y * b.x;
}

inline bool Clockwise(const Pos &a, const Pos &b, const Pos &c) {
  return Cross(a, b) + Cross(b, c) + Cross(c, a) < 0;
}

pair<Pos, double> ComputeCircle(const Pos &p, const Pos &q, const Pos &r) {
  double a = -2.0 * (p.x - q.x);
  double b = -2.0 * (p.y - q.y);
  double c = Square(p.x) + Square(p.y) - Square(q.x) - Square(q.y);
  double d = -2.0 * (p.x - r.x);
  double e = -2.0 * (p.y - r.y);
  double f = Square(p.x) + Square(p.y) - Square(r.x) - Square(r.y);
  double k = 1.0 / (b * d - a * e);
  double x = (c * e - f * b) * k;
  double y = -(c * d - f * a) * k;
  double rad = sqrt(Square(p.x - x) + Square(p.y - y));
  return MP(Pos{x, y}, rad);
}

struct Arc {
  int par;
  Pos p1, p2;
  bool left;
  double BreakPoint() const {
    if (p1.y - lineY < eps)
      return p1.x;
    if (p2.y - lineY < eps)
      return p2.x;
    double k1 = 1.0 / (p1.y - lineY);
    //	double k1=0.5/(p1.y-lineY);
    double k2 = 1.0 / (p2.y - lineY);
    //	double k2=0.5/(p2.y-lineY);
    double a = k1 - k2;
    double b = -2.0 * p1.x * k1 + 2.0 * p2.x * k2;
    double c = (Square(p1.x) + Square(p1.y) - Square(lineY)) * k1 -
               (Square(p2.x) + Square(p2.y) - Square(lineY)) * k2;
    if (abs(a) < eps)
      return -c / b;
    double d = b * b - 4.0 * a * c;
    assert(d > 0);
    double r = sqrt(d);
    double k = 0.5 / a;
    double s1 = (-b - r) * k;
    double s2 = (-b + r) * k;
    return s1 > s2 != left ? s1 : s2;
  }
};

inline bool operator<(const Arc &lhs, const Arc &rhs) {
  return lhs.BreakPoint() < rhs.BreakPoint();
}

struct Event {
  double y;
  int id;
  double x;
};

bool operator<(const Event &lhs, const Event &rhs) { return lhs.y < rhs.y; }

multiset<Arc> arcs;
priority_queue<Event> evs;

void AddSite(int);
void AddCircle(const Pos &, const Pos &, const Pos &);
void RemoveArc(double);

void Delaunay() {
  REP(i, n)
  evs.push(Event{sites[i].y, i});
  vector<pair<double, int>> tops;
  double last = -inf;
  while (!evs.empty()) {
    Event e = evs.top();
    if (e.y >= last) {
      last = e.y;
      tops.PB(MP(sites[e.id].x, e.id));
      evs.pop();
    } else
      break;
  }
  sort(tops.begin(), tops.end());
  int s = tops.size();
  auto itr = arcs.insert(Arc{tops[s - 1].second, Pos{inf, -inf}});
  for (int i = s - 2; i >= 0; i--) {
    AddEdge(tops[i].second, tops[i + 1].second);
    itr = arcs.insert(
        Arc{tops[i].second, sites[tops[i].second], sites[tops[i + 1].second]});
  }
  while (!evs.empty()) {
    Event e = evs.top();
    evs.pop();
    lineY = e.y;
    if (e.id != -1)
      AddSite(e.id);
    else
      RemoveArc(e.x);
  }
}

void AddSite(int p) {
  auto itr = arcs.lower_bound(Arc{-1, Pos{sites[p].x - eps, -inf}});
  int q = itr->par;

  /*	cout<<"\\nAdd "<<p<<" under "<<q<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/

  itr = arcs.insert(itr, Arc{q, sites[q], sites[p], true});
  itr++;
  while (1) {
    if (itr->BreakPoint() < sites[p].x + eps)
      itr = arcs.erase(itr);
    else
      break;
  }
  int r = itr->par;
  itr = arcs.insert(itr, Arc{p, sites[r], sites[p], false});
  int u, v;
  {
    auto j = itr;
    Arc a, c = *j, b = *--j;
    if (j != arcs.begin()) {
      a = *--j;
      //	cout<<"a"<<endl;
      AddCircle(sites[a.par], sites[b.par], sites[c.par]);
    }
    u = b.par;
  }
  {
    auto j = itr;
    Arc a = *j++, b = *j++, c;
    if (j != arcs.end()) {
      c = *j;
      //	cout<<"b"<<endl;
      AddCircle(sites[a.par], sites[b.par], sites[c.par]);
    }
    v = b.par;
  }
  AddEdge(u, p);
  if (u != v)
    AddEdge(v, p);

  /*	cout<<"\\nAdded"<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/
}

void AddCircle(const Pos &a, const Pos &b, const Pos &c) {
  if (!Clockwise(a, b, c))
    return;
  /*	cout<<"Add Circle"<<endl;
          a.dbgOut();
          b.dbgOut();
          c.dbgOut();*/
  auto cr = ComputeCircle(a, b, c);
  evs.push(Event{cr.first.y - cr.second, -1, cr.first.x});
}

void RemoveArc(double x) {
  /*	cout<<"\\nRemove "<<"Y "<<lineY<<" X "<<x<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/

  auto itr = arcs.lower_bound(Arc{-1, Pos{x - eps, -inf}});

  /*	cout<<"c"<<endl;
          itr->p1.dbgOut();
          itr->p2.dbgOut();*/

  assert(itr != arcs.end());
  itr++;
  if (itr == arcs.end())
    return;
  if (sites[itr->par].y - lineY < eps)
    return;
  bool erased = false;
  while (1) {
    if (itr->BreakPoint() < x + eps) {
      itr = arcs.erase(itr);
      erased = true;
    } else
      break;
  }
  if (!erased)
    return;
  assert(itr != arcs.end());
  Arc a{-2}, d{-2}, c = *itr, b = *--itr;
  b = Arc{b.par, sites[b.par], sites[c.par], sites[b.par].y > sites[c.par].y};
  itr = arcs.erase(itr);
  itr = arcs.insert(itr, b);
  {
    auto j = itr;
    ++j;
    if (++j != arcs.end())
      d = *j;
  }
  {
    auto j = itr;
    if (j != arcs.begin())
      a = *--j;
  }
  AddEdge(b.par, c.par);
  if (a.par != -2)
    AddCircle(sites[a.par], sites[b.par], sites[c.par]);
  if (d.par != -2)
    AddCircle(sites[b.par], sites[c.par], sites[d.par]);

  /*	cout<<endl<<"Erased"<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/
}

int main() {
  n = read();
  REP(i, n) {
    sites[i].x = read();
    sites[i].y = read();
  }
  Delaunay();

  int ans = 1145141919;
  REP(i, n)
  for (auto c : graph[i]) {
    ans = min(ans, (int)(Square(sites[i].x - sites[c].x) +
                         Square(sites[i].y - sites[c].y)));
  }
  printf("%d\\n", ans);
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>

#define FOR(i, a, b) for (int i = a; i < b; i++)
#define REP(i, b) FOR(i, 0, b)
#define MP make_pair
#define PB push_back

using namespace std;

int read() {
  int i;
  scanf("%d", &i);
  return i;
}

const int Nmax = 500000;
int n;

const double eps = 1e-9;
const double inf = 1e10;
double lineY;

struct Pos {
  double x, y;
  void dbgOut() const { cout << "x " << x << " y " << y << endl; }
} sites[Nmax];

vector<int> graph[Nmax];

void AddEdge(int a, int b) {
  if (0 <= a && a < Nmax && 0 <= b && b < Nmax) {
    graph[a].PB(b);
    graph[b].PB(a);
  }
}

inline double Square(double x) { return x * x; }

inline double Cross(const Pos &a, const Pos &b) {
  return a.x * b.y - a.y * b.x;
}

inline bool Clockwise(const Pos &a, const Pos &b, const Pos &c) {
  return Cross(a, b) + Cross(b, c) + Cross(c, a) < 0;
}

pair<Pos, double> ComputeCircle(const Pos &p, const Pos &q, const Pos &r) {
  double a = -2.0 * (p.x - q.x);
  double b = -2.0 * (p.y - q.y);
  double c = Square(p.x) + Square(p.y) - Square(q.x) - Square(q.y);
  double d = -2.0 * (p.x - r.x);
  double e = -2.0 * (p.y - r.y);
  double f = Square(p.x) + Square(p.y) - Square(r.x) - Square(r.y);
  double k = 1.0 / (b * d - a * e);
  double x = (c * e - f * b) * k;
  double y = -(c * d - f * a) * k;
  double rad = sqrt(Square(p.x - x) + Square(p.y - y));
  return MP(Pos{x, y}, rad);
}

struct Arc {
  int par;
  Pos p1, p2;
  bool left;
  double BreakPoint() const {
    if (p1.y - lineY < eps)
      return p1.x;
    if (p2.y - lineY < eps)
      return p2.x;
    double k1 = 1.0 / (p1.y - lineY);
    //	double k1=0.5/(p1.y-lineY);
    double k2 = 1.0 / (p2.y - lineY);
    //	double k2=0.5/(p2.y-lineY);
    double a = k1 - k2;
    double b = -2.0 * p1.x * k1 + 2.0 * p2.x * k2;
    double c = (Square(p1.x) + Square(p1.y) - Square(lineY)) * k1 -
               (Square(p2.x) + Square(p2.y) - Square(lineY)) * k2;
    if (abs(a) < eps)
      return -c / b;
    double d = b * b - 4.0 * a * c;
    assert(d > 0);
    double r = sqrt(d);
    double k = 0.5 / a;
    double s1 = (-b - r) * k;
    double s2 = (-b + r) * k;
    return s1 > s2 != left ? s1 : s2;
  }
};

inline bool operator<(const Arc &lhs, const Arc &rhs) {
  return lhs.BreakPoint() < rhs.BreakPoint();
}

struct Event {
  double y;
  int id;
  double x;
};

bool operator<(const Event &lhs, const Event &rhs) { return lhs.y < rhs.y; }

multiset<Arc> arcs;
priority_queue<Event> evs;

void AddSite(int);
void AddCircle(const Pos &, const Pos &, const Pos &);
void RemoveArc(double);

void Delaunay() {
  REP(i, n)
  evs.push(Event{sites[i].y, i});
  vector<pair<double, int>> tops;
  double last = -inf;
  while (!evs.empty()) {
    Event e = evs.top();
    if (e.y >= last) {
      last = e.y;
      tops.PB(MP(sites[e.id].x, e.id));
      evs.pop();
    } else
      break;
  }
  sort(tops.begin(), tops.end());
  int s = tops.size();
  auto itr = arcs.insert(Arc{tops[s - 1].second, Pos{inf, -inf}});
  for (int i = s - 2; i >= 0; i--) {
    AddEdge(tops[i].second, tops[i + 1].second);
    itr = arcs.insert(
        Arc{tops[i].second, sites[tops[i].second], sites[tops[i + 1].second]});
  }
  while (!evs.empty()) {
    Event e = evs.top();
    evs.pop();
    lineY = e.y;
    if (e.id != -1)
      AddSite(e.id);
    else
      RemoveArc(e.x);
  }
}

void AddSite(int p) {
  auto itr = arcs.lower_bound(Arc{-1, Pos{sites[p].x - eps, -inf}});
  int q = itr->par;

  /*	cout<<"\\nAdd "<<p<<" under "<<q<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/

  itr = arcs.insert(itr, Arc{q, sites[q], sites[p], true});
  itr++;
  while (1) {
    if (itr->BreakPoint() < sites[p].x + eps)
      itr = arcs.erase(itr);
    else
      break;
  }
  int r = itr->par;
  itr = arcs.insert(itr, Arc{p, sites[r], sites[p], false});
  int u, v;
  {
    auto j = itr;
    Arc a, c = *j, b = *--j;
    if (j != arcs.begin()) {
      a = *--j;
      //	cout<<"a"<<endl;
      AddCircle(sites[a.par], sites[b.par], sites[c.par]);
    }
    u = b.par;
  }
  {
    auto j = itr;
    Arc a = *j++, b = *j++, c;
    if (j != arcs.end()) {
      c = *j;
      //	cout<<"b"<<endl;
      AddCircle(sites[a.par], sites[b.par], sites[c.par]);
    }
    v = b.par;
  }
  AddEdge(u, p);
  if (u != v)
    AddEdge(v, p);

  /*	cout<<"\\nAdded"<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/
}

void AddCircle(const Pos &a, const Pos &b, const Pos &c) {
  if (!Clockwise(a, b, c))
    return;
  /*	cout<<"Add Circle"<<endl;
          a.dbgOut();
          b.dbgOut();
          c.dbgOut();*/
  auto cr = ComputeCircle(a, b, c);
  evs.push(Event{cr.first.y - cr.second, -1, cr.first.x});
}

void RemoveArc(double x) {
  /*	cout<<"\\nRemove "<<"Y "<<lineY<<" X "<<x<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/

  auto itr = arcs.lower_bound(Arc{-1, Pos{x - eps, -inf}});

  /*	cout<<"c"<<endl;
          itr->p1.dbgOut();
          itr->p2.dbgOut();*/

  assert(itr != arcs.end());
  itr++;
  if (itr->p1.y - lineY < eps)
    return;
  bool erased = false;
  while (1) {
    if (itr->BreakPoint() < x + eps) {
      itr = arcs.erase(itr);
      erased = true;
    } else
      break;
  }
  if (!erased)
    return;
  assert(itr != arcs.end());
  Arc a{-2}, d{-2}, c = *itr, b = *--itr;
  b = Arc{b.par, sites[b.par], sites[c.par], sites[b.par].y > sites[c.par].y};
  itr = arcs.erase(itr);
  itr = arcs.insert(itr, b);
  {
    auto j = itr;
    ++j;
    if (++j != arcs.end())
      d = *j;
  }
  {
    auto j = itr;
    if (j != arcs.begin())
      a = *--j;
  }
  AddEdge(b.par, c.par);
  if (a.par != -2)
    AddCircle(sites[a.par], sites[b.par], sites[c.par]);
  if (d.par != -2)
    AddCircle(sites[b.par], sites[c.par], sites[d.par]);

  /*	cout<<endl<<"Erased"<<endl;
          for(const auto& arc:arcs){
                  cout<<"Par "<<arc.par<<" BreakPoint "<<arc.BreakPoint()<<endl;
                  arc.p1.dbgOut();
                  arc.p2.dbgOut();
          }*/
}

int main() {
  n = read();
  REP(i, n) {
    sites[i].x = read();
    sites[i].y = read();
  }
  Delaunay();

  int ans = 1145141919;
  REP(i, n)
  for (auto c : graph[i])
    ans = min(ans, (int)(Square(sites[i].x - sites[c].x) +
                         Square(sites[i].y - sites[c].y)));
  printf("%d\\n", ans);
}