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

#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

typedef long double R;
typedef complex<R> P;

const R EPS = 1e-10;
const R PI = acos((R)(-1));

/*
 -1 -> neg
  0 -> near 0
  1 -> pos
  */
int sgn(R a) {
  if (a < -EPS)
    return -1;
  if (a > EPS)
    return 1;
  return 0;
}

/*
 -1 -> a > b
 0 -> a near b
 1 -> a < b
 */
int sgn(R a, R b) { return sgn(b - a); }

bool near(const P &a, const P &b) { return !sgn(abs(a - b)); }

R cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }
R dot(P a, P b) { return a.real() * b.real() + a.imag() * b.imag(); }

/* 1->cclock
  -1->clock
   0->on
   2->back
  -2->front
  */
int ccw(P a, P b, P c) {
  assert(!near(a, b));
  if (near(a, c) || near(b, c))
    return 0;
  int s = sgn(cross(b - a, c - a));
  if (s)
    return s;
  if (dot(b - a, c - a) < 0)
    return 2;
  if (dot(a - b, c - b) < 0)
    return -2;
  return 0;
}

struct L {
  P x, y;
  L() {}
  L(P x, P y) : x(x), y(y) {}
};

P vec(const L &l) { return l.y - l.x; }

R abs(const L &l) { return abs(vec(l)); }

R arg(const L &l) { return arg(vec(l)); }

//?§???????[0, 2*PI)???
R radNorP(R x) { return fmod(fmod(x, 2 * PI) + 2 * PI, 2 * PI); }

//?§???????[-PI, PI)???
R radNorN(R x) {
  x = radNorP(x);
  if (x >= PI)
    x -= 2 * PI;
  return x;
}

struct C {
  P p;
  R r;
  C() {}
  C(P p, R r) : p(p), r(r) {}
};

typedef vector<P> Pol;

P cu(const Pol &p, int i) {
  int s = p.size();
  return p[(i % s + s) % s];
};

R area(const Pol &p) {
  R u = 0;
  for (int i = 0; i < (int)p.size(); i++) {
    u += cross(cu(p, i), cu(p, i + 1));
  }
  return abs(u) / 2;
}

// 0:P is out 1:P is on line 2:P is in
int contains(const Pol &pol, P p) {
  int in = -1;
  for (int i = 0; i < (int)pol.size(); i++) {
    P a = cu(pol, i) - p, b = cu(pol, i + 1) - p;
    if (ccw(a, b, P(0, 0)) == 0)
      return 1;
    if (imag(a) > imag(b))
      swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b)) {
      if (cross(a, b) < 0)
        in *= -1;
    }
  }
  return in + 1;
}

// true:Polygon is counter_cycle false:cycle
bool iscclock(const Pol &pol) {
  double th = 0;
  for (int i = 0; i < (int)pol.size(); i++) {
    P a = cu(pol, i), b = cu(pol, i + 1), c = cu(pol, i + 2);
    th += radNorN(arg(c - b) - arg(b - a));
  }
  return (th > 0);
}

/*
 ????????°???????????????
 pol, rg???????´????2*n-4????¢?????????????????????¨
 g??????????????????????????´?£??????????
 */
int dualGraph(P p[], vector<int> g[], int n, Pol pol[], vector<int> rg[]) {

  map<pair<int, int>, int> mp;
  for (int i = 0; i < n; i++) {
    sort(g[i].begin(), g[i].end(), [&](int l, int r) {
      assert(!near(p[l], p[i]) && !near(p[r], p[i]));
      return arg(p[l] - p[i]) > arg(p[r] - p[i]);
    });
    assert(unique(g[i].begin(), g[i].end()) == g[i].end());
    for (int j = 0; j < (int)g[i].size(); j++) {
      mp[make_pair(i, g[i][j])] = j;
    }
  }

  vector<vector<int>> idx(n), rev(n);
  for (int i = 0; i < n; i++) {
    idx[i] = vector<int>(g[i].size(), -1);
    rev[i].resize(g[i].size());
    for (int j = 0; j < (int)g[i].size(); j++) {
      assert(mp.count(make_pair(g[i][j], i)));
      rev[i][j] = mp[make_pair(g[i][j], i)];
    }
  }

  int idc = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (int)g[i].size(); j++) {
      if (idx[i][j] != -1)
        continue;
      Pol po;
      int ii = i, jj = j;
      while (idx[ii][jj] != -2) {
        po.push_back(p[ii]);
        idx[ii][jj] = -2;
        int ni = g[ii][jj];
        int nj = (rev[ii][jj] + 1) % g[ni].size();
        ii = ni;
        jj = nj;
      }
      int id;
      if (area(po) == 0 || !iscclock(po)) {
        id = -3;
      } else {
        id = idc;
        pol[idc] = po;
        idc++;
      }
      while (idx[ii][jj] == -2) {
        po.push_back(p[ii]);
        idx[ii][jj] = id;
        int ni = g[ii][jj];
        int nj = (rev[ii][jj] + 1) % g[ni].size();
        ii = ni;
        jj = nj;
      }
    }
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (int)g[i].size(); j++) {
      if (idx[i][j] < 0)
        continue;
      rg[idx[i][j]].push_back(idx[g[i][j]][rev[i][j]]);
    }
  }
  for (int i = 0; i < n; i++) {
    sort(rg[i].begin(), rg[i].end());
    rg[i].erase(unique(rg[i].begin(), rg[i].end()), rg[i].end());
  }
  return idc;
}

const int MN = 110;
C c[MN];
P p[MN];
Pol po[2 * MN];
vector<int> g[MN];
vector<int> rg[2 * MN];
bool solve() {
  int n, m;
  cin >> n >> m;
  if (!n && !m)
    return false;
  for (int i = 0; i < n; i++) {
    R x, y, r;
    cin >> x >> y >> r;
    p[i] = P(x, y);
    c[i] = C(p[i], r);
  }

  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      if (i == j)
        continue;
      R di = abs(c[i].p - c[j].p);
      if (abs(c[i].r - c[j].r) < di && di < c[i].r + c[j].r) {
        g[i].push_back(j);
        g[j].push_back(i);
      }
    }
  }

  int u = dualGraph(p, g, n, po, rg);
  string result;
  for (int i = 0; i < m; i++) {
    R ax, ay, bx, by;
    cin >> ax >> ay >> bx >> by;
    P a = P(ax, ay);
    P b = P(bx, by);
    vector<int> aid, bid;
    for (int j = 0; j < n; j++) {
      if (abs(c[j].p - a) < c[j].r) {
        aid.push_back(j);
      }
      if (abs(c[j].p - b) < c[j].r) {
        bid.push_back(j);
      }
    }
    sort(aid.begin(), aid.end());
    sort(bid.begin(), bid.end());
    if (aid != bid) {
      result += "NO ";
      continue;
    }
    if (aid.size()) {
      result += "YES ";
      continue;
    }
    aid.clear();
    bid.clear();
    for (int j = 0; j < u; j++) {
      if (contains(po[j], a)) {
        aid.push_back(j);
      }
      if (contains(po[j], b)) {
        bid.push_back(j);
      }
    }
    sort(aid.begin(), aid.end());
    sort(bid.begin(), bid.end());
    if (aid == bid) {
      result += "YES ";
      continue;
    } else {
      result += "NO ";
      continue;
    }
  }
  result.resize((int)result.size() - 1);
  cout << result << endl;
  return true;
}

int main() {
  while (solve()) {
  }
  return 0;
}

Error: WA

Fixed submission:

#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

typedef long double R;
typedef complex<R> P;

const R EPS = 1e-10;
const R PI = acos((R)(-1));

/*
 -1 -> neg
  0 -> near 0
  1 -> pos
  */
int sgn(R a) {
  if (a < -EPS)
    return -1;
  if (a > EPS)
    return 1;
  return 0;
}

/*
 -1 -> a > b
 0 -> a near b
 1 -> a < b
 */
int sgn(R a, R b) { return sgn(b - a); }

bool near(const P &a, const P &b) { return !sgn(abs(a - b)); }

R cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }
R dot(P a, P b) { return a.real() * b.real() + a.imag() * b.imag(); }

/* 1->cclock
  -1->clock
   0->on
   2->back
  -2->front
  */
int ccw(P a, P b, P c) {
  assert(!near(a, b));
  if (near(a, c) || near(b, c))
    return 0;
  int s = sgn(cross(b - a, c - a));
  if (s)
    return s;
  if (dot(b - a, c - a) < 0)
    return 2;
  if (dot(a - b, c - b) < 0)
    return -2;
  return 0;
}

struct L {
  P x, y;
  L() {}
  L(P x, P y) : x(x), y(y) {}
};

P vec(const L &l) { return l.y - l.x; }

R abs(const L &l) { return abs(vec(l)); }

R arg(const L &l) { return arg(vec(l)); }

//?§???????[0, 2*PI)???
R radNorP(R x) { return fmod(fmod(x, 2 * PI) + 2 * PI, 2 * PI); }

//?§???????[-PI, PI)???
R radNorN(R x) {
  x = radNorP(x);
  if (x >= PI)
    x -= 2 * PI;
  return x;
}

struct C {
  P p;
  R r;
  C() {}
  C(P p, R r) : p(p), r(r) {}
};

typedef vector<P> Pol;

P cu(const Pol &p, int i) {
  int s = p.size();
  return p[(i % s + s) % s];
};

R area(const Pol &p) {
  R u = 0;
  for (int i = 0; i < (int)p.size(); i++) {
    u += cross(cu(p, i), cu(p, i + 1));
  }
  return abs(u) / 2;
}

// 0:P is out 1:P is on line 2:P is in
int contains(const Pol &pol, P p) {
  int in = -1;
  for (int i = 0; i < (int)pol.size(); i++) {
    P a = cu(pol, i) - p, b = cu(pol, i + 1) - p;
    if (ccw(a, b, P(0, 0)) == 0)
      return 1;
    if (imag(a) > imag(b))
      swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b)) {
      if (cross(a, b) < 0)
        in *= -1;
    }
  }
  return in + 1;
}

// true:Polygon is counter_cycle false:cycle
bool iscclock(const Pol &pol) {
  double th = 0;
  for (int i = 0; i < (int)pol.size(); i++) {
    P a = cu(pol, i), b = cu(pol, i + 1), c = cu(pol, i + 2);
    th += radNorN(arg(c - b) - arg(b - a));
  }
  return (th > 0);
}

/*
 ????????°???????????????
 pol, rg???????´????2*n-4????¢?????????????????????¨
 g??????????????????????????´?£??????????
 */
int dualGraph(P p[], vector<int> g[], int n, Pol pol[], vector<int> rg[]) {

  map<pair<int, int>, int> mp;
  for (int i = 0; i < n; i++) {
    sort(g[i].begin(), g[i].end(),
         [&](int l, int r) { return arg(p[l] - p[i]) > arg(p[r] - p[i]); });
    assert(unique(g[i].begin(), g[i].end()) == g[i].end());
    for (int j = 0; j < (int)g[i].size(); j++) {
      mp[make_pair(i, g[i][j])] = j;
    }
  }

  vector<vector<int>> idx(n), rev(n);
  for (int i = 0; i < n; i++) {
    idx[i] = vector<int>(g[i].size(), -1);
    rev[i].resize(g[i].size());
    for (int j = 0; j < (int)g[i].size(); j++) {
      assert(mp.count(make_pair(g[i][j], i)));
      rev[i][j] = mp[make_pair(g[i][j], i)];
    }
  }

  int idc = 1;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (int)g[i].size(); j++) {
      if (idx[i][j] != -1)
        continue;
      Pol po;
      int ii = i, jj = j;
      while (idx[ii][jj] != -2) {
        po.push_back(p[ii]);
        idx[ii][jj] = -2;
        int ni = g[ii][jj];
        int nj = (rev[ii][jj] + 1) % g[ni].size();
        ii = ni;
        jj = nj;
      }
      int id;
      if (area(po) == 0) {
        id = -3;
      } else if (!iscclock(po)) {
        id = 0;
      } else {
        id = idc;
        pol[idc] = po;
        idc++;
      }
      while (idx[ii][jj] == -2) {
        po.push_back(p[ii]);
        idx[ii][jj] = id;
        int ni = g[ii][jj];
        int nj = (rev[ii][jj] + 1) % g[ni].size();
        ii = ni;
        jj = nj;
      }
    }
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (int)g[i].size(); j++) {
      if (idx[i][j] < 0)
        continue;
      rg[idx[i][j]].push_back(idx[g[i][j]][rev[i][j]]);
    }
  }
  for (int i = 0; i < n; i++) {
    sort(rg[i].begin(), rg[i].end());
    rg[i].erase(unique(rg[i].begin(), rg[i].end()), rg[i].end());
  }
  return idc;
}

const int MN = 110;
C c[MN];
P p[MN];
Pol po[2 * MN];
vector<int> g[MN];
vector<int> rg[2 * MN];
bool solve() {
  int n, m;
  cin >> n >> m;
  if (!n && !m)
    return false;
  for (int i = 0; i < n; i++) {
    R x, y, r;
    cin >> x >> y >> r;
    p[i] = P(x, y);
    c[i] = C(p[i], r);
  }

  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      if (i == j)
        continue;
      if (abs(c[i].p - c[j].p) < c[i].r + c[j].r) {
        g[i].push_back(j);
        g[j].push_back(i);
      }
    }
  }

  int u = dualGraph(p, g, n, po, rg);
  for (int i = 0; i < m; i++) {
    R ax, ay, bx, by;
    cin >> ax >> ay >> bx >> by;
    P a = P(ax, ay);
    P b = P(bx, by);
    int aid = -1, bid = -1;
    for (int j = 0; j < n; j++) {
      if (abs(c[j].p - a) < c[j].r) {
        if ((aid == -1) || c[j].r < c[aid].r) {
          aid = j;
        }
      }
      if (abs(c[j].p - b) < c[j].r) {
        if ((bid == -1) || c[j].r < c[bid].r) {
          bid = j;
        }
      }
    }
    //        cout << aid << " " << bid << endl;
    if (aid != bid) {
      cout << "NO ";
      continue;
    }
    if (aid != -1) {
      cout << "YES ";
      continue;
    }
    for (int j = 1; j < u; j++) {
      if (contains(po[j], a)) {
        if ((aid == -1) || area(po[j]) < area(po[aid])) {
          aid = j;
        }
      }
      if (contains(po[j], b)) {
        if ((bid == -1) || area(po[j]) < area(po[bid])) {
          bid = j;
        }
      }
    }
    if (aid == bid) {
      cout << "YES ";
      continue;
    } else {
      cout << "NO ";
      continue;
    }
  }
  cout << endl;
  return true;
}

int main() {
  while (solve()) {
  }
  return 0;
}