Problem p00779 (C++) — buggy submission, verdict: Memory Limit Exceeded

// Type.
typedef int Label;
typedef double Weight;
struct Vertex {
  Label label;
  double x, y;
};
struct Edge {
  Label from, to;
  Weight weight;
};
// Library.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
// Class.
template <typename Vertex, typename Edge> class PlaneGraph {
public:
  void insert(const Vertex &v);
  void insert(Edge e);
  const std::vector<std::vector<Edge>>
  dualgraph(const Weight &weight = Weight()) const;

private:
  const std::vector<Edge>
  dualgraph_color(std::map<Label, std::map<Label, Label>> &color,
                  const Label &c, const Edge &e,
                  const std::map<Label, std::vector<Edge>> &edge) const;
  std::map<Label, Vertex> V;
  std::map<Label, std::vector<Edge>> E;
};
// Implement.
template <typename Vertex, typename Edge>
void PlaneGraph<Vertex, Edge>::insert(const Vertex &v) {
  V[v.label] = v;
}
template <typename Vertex, typename Edge>
void PlaneGraph<Vertex, Edge>::insert(Edge e) {
  assert(V.find(e.from) != std::end(V));
  assert(V.find(e.to) != std::end(V));
  E[e.from].push_back(e);
  std::swap(e.from, e.to);
  E[e.from].push_back(e);
}
template <typename Vertex, typename Edge>
const std::vector<std::vector<Edge>>
PlaneGraph<Vertex, Edge>::dualgraph(const Weight &weight) const {
  // Sort edges counterclockwise.
  auto edge = E;
  for (auto &list : edge)
    if (!list.second.empty()) {
      std::sort(std::begin(list.second), std::end(list.second),
                [&](const Edge &lhs, const Edge &rhs) {
                  double l = std::atan2(V.at(lhs.to).y - V.at(lhs.from).y,
                                        V.at(lhs.to).x - V.at(lhs.from).x);
                  double r = std::atan2(V.at(rhs.to).y - V.at(rhs.from).y,
                                        V.at(rhs.to).x - V.at(rhs.from).x);
                  return l < r;
                });
      list.second.push_back(list.second.front());
    }
  // Color edges.
  std::vector<std::vector<Edge>> result;
  std::map<Label, std::map<Label, Label>> color;
  Label c = Label();
  for (const auto &list : edge)
    for (const auto &e : list.second)
      if (!color[e.from].count(e.to)) {
        auto add = dualgraph_color(color, c++, e, edge);
        //     if(add.size() < 3) continue;
        result.push_back(add);
      }
  return result;
}
template <typename Vertex, typename Edge>
const std::vector<Edge> PlaneGraph<Vertex, Edge>::dualgraph_color(
    std::map<Label, std::map<Label, Label>> &color, const Label &c,
    const Edge &e, const std::map<Label, std::vector<Edge>> &edge) const {
  std::vector<Edge> result = {e};
  color[e.from][e.to] = c;
  for (auto it = edge.at(e.to).rbegin(); it != edge.at(e.to).rend(); ++it)
    if (it->to == e.from) {
      ++it;
      if (!color[it->from].count(it->to)) {
        auto add = dualgraph_color(color, c, *it, edge);
        result.insert(std::end(result), std::begin(add), std::end(add));
      }
      break;
    }
  return result;
}
////////////////////////////////////////
// Union-Find.
#include <unordered_map>
#include <utility>
template <typename T> class UnionFind {
public:
  void unite(const T &a, const T &b) {
    T x = find(a), y = find(b);
    if (rank_[x] < rank_[y])
      std::swap(x, y);
    parent_[y] = x;
    if (rank_[x] == rank_[y])
      rank_[x] += 1;
  }
  const T find(const T &x) {
    if (!parent_.count(x)) {
      rank_[x] = 1;
      return parent_[x] = x;
    }
    return (parent_[x] == x) ? x : (parent_[x] = find(parent_[x]));
  }

private:
  std::unordered_map<T, T> parent_;
  std::unordered_map<T, int> rank_;
};
////////////////////////////////////////
// Geometry.
struct Point {
  double x, y;
};
struct Circle {
  double x, y, r;
};
double distance(const Point &lhs, const Point &rhs) {
  return std::hypot(lhs.x - rhs.x, lhs.y - rhs.y);
}
bool include(const Circle &c, const Point &p) {
  return distance({c.x, c.y}, p) <= c.r;
}
bool intersect(const Circle &lhs, const Circle &rhs) {
  double d = distance({lhs.x, lhs.y}, {rhs.x, rhs.y});
  if (d + std::min(lhs.r, rhs.r) < std::max(lhs.r, rhs.r))
    return false;
  return d <= lhs.r + rhs.r;
}
double norm(const Point &p) { return p.x * p.x + p.y * p.y; }
double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
double cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
// 3??????????????¢???
const double INF = 1e9;
const double EPS = 1e-9; // |EPS|???????????°???0??¨????????±???
enum POSITION {
  ONLINE_FRONT = -2,
  CLOCKWISE,
  ON_SEGMENT,
  COUNTER_CLOCKWISE,
  ONLINE_BACK
};
POSITION ccw(const Point &a, const Point &b, const Point &p) {
  Point v1 = b;
  Point v2 = p;
  v1.x -= a.x;
  v1.y -= a.y;
  v2.x -= a.x;
  v2.y -= a.y;
  if (cross(v1, v2) >= EPS)
    return COUNTER_CLOCKWISE;
  if (cross(v1, v2) <= -EPS)
    return CLOCKWISE;
  if (dot(v1, v2) <= -EPS)
    return ONLINE_BACK;
  if (norm(v1) < norm(v2))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
// bool intersect(const Point& s1i, const Point& s1t, const Point& s2i) {
//   Point s2t = {INF, s2i.y};
//   return ccw(s1i, s1t, s2i) * ccw(s1i, s1t, s2t) <= 0
//       && ccw(s2i, s2t, s1i) * ccw(s2i, s2t, s1t) <= 0;
// }
bool include(const std::vector<Circle> &circle, const std::vector<Edge> &edge,
             const Point &p) {
  bool in = false;
  for (const auto &e : edge) {
    Point a = {circle[e.from].x, circle[e.from].y};
    Point b = {circle[e.to].x, circle[e.to].y};
    a.x -= p.x;
    a.y -= p.y;
    b.x -= p.x;
    b.y -= p.y;
    if (a.y > b.y)
      std::swap(a, b);
    if (a.y <= 0 && 0 < b.y && cross(a, b) < 0)
      in = !in;
    if (std::abs(cross(a, b)) <= EPS && dot(a, b) <= EPS)
      return true;
  }
  return in;
}
////////////////////////////////////////
#include <bits/stdc++.h>
using namespace std;
struct Query {
  double sx, sy, gx, gy;
};
bool check(const vector<Circle> &circle, vector<vector<Edge>> &cycle,
           const Query &q) {
  Point P({q.sx, q.sy}), Q({q.gx, q.gy});
  for (const auto &c : circle)
    if (include(c, P) != include(c, Q))
      return false;
  for (const auto &list : cycle) {
    bool in = false;
    for (const auto &e : list)
      if (include(circle[e.from], P) || include(circle[e.from], Q))
        in = true;
    if (in)
      continue;
    if (include(circle, list, P) != include(circle, list, Q))
      return false;
  }
  return true;
}
int main() {
  int n, m;
  while (cin >> n >> m, n | m) {
    vector<Circle> circle(n);
    for (auto &c : circle)
      cin >> c.x >> c.y >> c.r;
    vector<Query> query(m);
    for (auto &q : query)
      cin >> q.sx >> q.sy >> q.gx >> q.gy;

    vector<Edge> E;
    UnionFind<int> uf;
    for (int i = 0; i < n; ++i)
      for (int j = i + 1; j < n; ++j)
        if (intersect(circle[i], circle[j])) {
          uf.unite(i, j);
          E.push_back({i, j, 1});
        }
    map<int, PlaneGraph<Vertex, Edge>> chain;
    for (int i = 0; i < n; ++i)
      chain[uf.find(i)].insert(Vertex{i, circle[i].x, circle[i].y});
    for (const auto &e : E)
      chain[uf.find(e.from)].insert(Edge({e.from, e.to, 1}));
    vector<vector<Edge>> cycle;
    for (const auto &c : chain) {
      auto add = c.second.dualgraph();
      cycle.insert(begin(cycle), begin(add), end(add));
    }

    for (int i = 0; i < m; ++i)
      cout << (i ? " " : "") << (check(circle, cycle, query[i]) ? "YES" : "NO");
    cout << endl;
  }
}

Error: MLE

Fixed submission:


#include <algorithm> // min(), sort(), reverse()
#include <cmath>     // fabs(), hypot()
#include <iostream>
#include <vector> // Circle::crosspoint()の戻り値, Polygonのメンバ変数

const double EPS = 1e-10;
enum POSITION {
  ONLINE_FRONT = -2,
  CLOCKWISE,
  ON_SEGMENT,
  COUNTER_CLOCKWISE,
  ONLINE_BACK
}; // ccw(a, b, p)で3点a, b, pの位置関係を返す
   //   0: a-p-b, 2: p-a-b, -2: a-b-p, 1: -a-b-の上にp, -1: -a-b-の下にp
// class
class Point;
class Segment;
class Line;
class Circle;
class Polygon;
// member
class Point {
  double x_value, y_value;

public:
  Point() : x_value(0.0), y_value(0.0) {}
  Point(double d) : x_value(d), y_value(d) {}
  Point(double a, double b) : x_value(a), y_value(b) {}
  double x() const { return x_value; }
  double y() const { return y_value; }
  double x(double d) { return x_value = d; }
  double y(double d) { return y_value = d; }
  const Point operator-() const;
  const Point &operator=(const Point &);
  const Point &operator+=(const Point &);
  const Point &operator-=(const Point &);
  const Point &operator*=(const Point &);
  const Point &operator/=(const Point &);
  double dot(const Point &) const;
  double cross(const Point &) const;
  double abs() const;
  double norm() const;
  const Point normalize() const;
  double distance(const Point &) const;
  double distance(const Segment &) const;
  double distance(const Line &) const;
  bool intersect(const Point &) const;
  bool intersect(const Segment &) const;
  bool intersect(const Line &) const;
  const Point projection(const Line &) const;
  const Point reflection(const Line &) const;
  POSITION ccw(const Point &, const Point &) const;
  void print() const;
};
bool operator==(const Point &lhs, const Point &rhs);
bool operator!=(const Point &lhs, const Point &rhs);
bool operator<(const Point &lhs, const Point &rhs);
bool operator>(const Point &lhs, const Point &rhs);
bool operator<=(const Point &lhs, const Point &rhs);
bool operator>=(const Point &lhs, const Point &rhs);
const Point operator+(const Point &lhs, const Point &rhs);
const Point operator-(const Point &lhs, const Point &rhs);
const Point operator*(const Point &lhs, const Point &rhs);
const Point operator/(const Point &lhs, const Point &rhs);
class Segment {
  Point source_point, target_point;

public:
  Segment(double x1 = 0.0, double y1 = 0.0, double x2 = 0.0, double y2 = 0.0)
      : source_point(Point(x1, y1)), target_point(Point(x2, y2)) {}
  Segment(const Point &a, const Point &b) : source_point(a), target_point(b) {}
  const Point &source() const { return source_point; }
  const Point &target() const { return target_point; }
  const Point &source(const Point &p) { return source_point = p; }
  const Point &target(const Point &p) { return target_point = p; }
  const Line line() const;
  double distance(const Point &) const;
  double distance(const Segment &) const;
  double distance(const Line &) const;
  bool intersect(const Point &) const;
  bool intersect(const Segment &) const;
  bool intersect(const Line &) const;
  bool parallel(const Segment &) const;
  bool parallel(const Line &) const;
  bool orthogonal(const Segment &) const;
  bool orthogonal(const Line &) const;
  POSITION ccw(const Point &) const;
  void print() const;
};
class Line {
  Point source_point, target_point;

public:
  Line(double x1 = 0.0, double y1 = 0.0, double x2 = 0.0, double y2 = 0.0)
      : source_point(Point(x1, y1)), target_point(Point(x2, y2)) {}
  Line(const Point &a, const Point &b) : source_point(a), target_point(b) {}
  const Point &source() const { return source_point; }
  const Point &target() const { return target_point; }
  const Point &source(const Point &p) { return source_point = p; }
  const Point &target(const Point &p) { return target_point = p; }
  const Segment segment() const;
  double distance(const Point &) const;
  double distance(const Segment &) const;
  double distance(const Line &) const;
  bool intersect(const Point &) const;
  bool intersect(const Segment &) const;
  bool intersect(const Line &) const;
  bool parallel(const Segment &) const;
  bool parallel(const Line &) const;
  bool orthogonal(const Segment &) const;
  bool orthogonal(const Line &) const;
  const Point projection(const Point &) const;
  const Point reflection(const Point &) const;
  const Point crosspoint(const Line &) const;
  POSITION ccw(const Point &) const;
  void print() const;
};
class Circle {
  Point center_point;
  double radius;

public:
  Circle(double a = 0.0, double b = 0.0, double c = 0.0)
      : center_point(Point(a, b)), radius(c) {}
  const Point &center() const { return center_point; }
  double x() const { return center_point.x(); }
  double y() const { return center_point.y(); }
  double r() const { return radius; }
  const Point &center(const Point &p) { return center_point = p; }
  double x(double d) { return center_point.x(d); }
  double y(double d) { return center_point.y(d); }
  double r(double d) { return radius = d; }
  bool in(const Point &) const;
  bool out(const Point &) const;
  bool include(const Point &) const;
  bool include(const Segment &) const;
  bool include(const Line &) const;
  bool include(const Circle &) const;
  bool intersect(const Circle &) const;
  std::vector<Point> crosspoint(const Circle &) const;
  void print() const;
};
class Polygon {
  std::vector<Point> point;

public:
  Polygon() {}
  explicit Polygon(std::vector<Point> p) : point(p) {}
  const std::vector<Point> &vertex() const { return point; }
  const Point &vertex(int i) const { return point.at(i); }
  const std::vector<Segment> edge() const {
    std::vector<Segment> result;
    for (int i = 0; i < size(); ++i)
      result.push_back(Segment(vertex(i), vertex((i + 1) % size())));
    return result;
  }
  const Segment edge(int i) const {
    return Segment(vertex(i), vertex((i + 1) % size()));
  }
  int size() const { return point.size(); }
  void add(const Point &);
  double area() const;
  bool convex() const;
  bool include(const Point &) const;
  bool intersect(const Polygon &) const;
  bool on_edge(const Point &) const;
  const Polygon convex_hull() const;
  void print() const;
};
// Point
bool operator==(const Point &lhs, const Point &rhs) {
  return lhs.x() == rhs.x() && lhs.y() == rhs.y();
}
bool operator!=(const Point &lhs, const Point &rhs) {
  return lhs.x() != rhs.x() || lhs.y() != rhs.y();
}
bool operator<(const Point &lhs, const Point &rhs) {
  return lhs.x() != rhs.x() ? lhs.x() < rhs.x() : lhs.y() < rhs.y();
}
bool operator>(const Point &lhs, const Point &rhs) {
  return lhs.x() != rhs.x() ? lhs.x() > rhs.x() : lhs.y() > rhs.y();
}
bool operator<=(const Point &lhs, const Point &rhs) {
  return lhs.x() != rhs.x() ? lhs.x() < rhs.x() : lhs.y() <= rhs.y();
}
bool operator>=(const Point &lhs, const Point &rhs) {
  return lhs.x() != rhs.x() ? lhs.x() > rhs.x() : lhs.y() >= rhs.y();
}
const Point operator+(const Point &lhs, const Point &rhs) {
  return Point(lhs.x() + rhs.x(), lhs.y() + rhs.y());
}
const Point operator-(const Point &lhs, const Point &rhs) {
  return Point(lhs.x() - rhs.x(), lhs.y() - rhs.y());
}
const Point operator*(const Point &lhs, const Point &rhs) {
  return Point(lhs.x() * rhs.x(), lhs.y() * rhs.y());
}
const Point operator/(const Point &lhs, const Point &rhs) {
  return Point(lhs.x() / rhs.x(), lhs.y() / rhs.y());
}
const Point Point::operator-() const { return Point(-x(), -y()); }
const Point &Point::operator=(const Point &p) {
  x(p.x());
  y(p.y());
  return *this;
}
const Point &Point::operator+=(const Point &p) { return *this = *this + p; }
const Point &Point::operator-=(const Point &p) { return *this = *this - p; }
const Point &Point::operator*=(const Point &p) { return *this = *this * p; }
const Point &Point::operator/=(const Point &p) { return *this = *this / p; }
double Point::dot(const Point &p) const { return x() * p.x() + y() * p.y(); }
double Point::cross(const Point &p) const { return x() * p.y() - y() * p.x(); }
double Point::abs() const { return hypot(x(), y()); }
double Point::norm() const { return x() * x() + y() * y(); }
const Point Point::normalize() const {
  return abs() == 0.0 ? Point(0.0, 0.0) : Point(x(), y()) / abs();
}
double Point::distance(const Point &p) const { return (p - (*this)).abs(); }
double Point::distance(const Segment &s) const { return s.distance(*this); }
double Point::distance(const Line &l) const { return l.distance(*this); }
bool Point::intersect(const Point &p) const { return *this == p; }
bool Point::intersect(const Segment &s) const { return s.intersect(*this); }
bool Point::intersect(const Line &l) const { return l.intersect(*this); }
const Point Point::projection(const Line &l) const {
  return l.projection(*this);
}
const Point Point::reflection(const Line &l) const {
  return l.reflection(*this);
}
POSITION Point::ccw(const Point &b, const Point &p) const {
  const Point &a = *this;
  Point v1 = b - a;
  Point v2 = p - a;
  if (v1.cross(v2) > EPS)
    return COUNTER_CLOCKWISE;
  if (v1.cross(v2) < -EPS)
    return CLOCKWISE;
  if (v1.dot(v2) < -EPS)
    return ONLINE_BACK;
  if (v2.norm() - v1.norm() > EPS)
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
void Point::print() const { std::cout << x() << ", " << y() << std::endl; }
// Segment
const Line Segment::line() const { return Line(source(), target()); }
double Segment::distance(const Point &p) const {
  Point q = line().projection(p);
  if (intersect(q))
    return q.distance(p);
  return std::min(source().distance(p), target().distance(p));
}
double Segment::distance(const Segment &s) const {
  if (intersect(s))
    return 0.0;
  double a = distance(s.source());
  double b = distance(s.target());
  double c = s.distance(source());
  double d = s.distance(target());
  return std::min({a, b, c, d});
}
double Segment::distance(const Line &l) const { return l.distance(*this); }
bool Segment::intersect(const Point &p) const {
  return source().distance(p) + target().distance(p) -
             target().distance(source()) <=
         EPS;
}
bool Segment::intersect(const Segment &s) const {
  bool a = ccw(s.source()) * ccw(s.target()) <= 0;
  bool b = s.ccw(source()) * s.ccw(target()) <= 0;
  return a && b;
}
bool Segment::intersect(const Line &l) const { return l.intersect(*this); }
bool Segment::parallel(const Line &l) const { line().parallel(l); }
bool Segment::parallel(const Segment &s) const {
  return line().parallel(s.line());
}
bool Segment::orthogonal(const Line &l) const { return line().orthogonal(l); }
bool Segment::orthogonal(const Segment &s) const {
  return line().orthogonal(s.line());
}
POSITION Segment::ccw(const Point &p) const {
  return source().ccw(target(), p);
}
void Segment::print() const {
  std::cout << "source: ";
  source().print();
  std::cout << "target: ";
  target().print();
}
// Line
const Segment Line::segment() const { return Segment(source(), target()); }
double Line::distance(const Point &p) const {
  return p.distance(projection(p));
}
double Line::distance(const Segment &s) const {
  if (intersect(s))
    return 0.0;
  double a = distance(s.source());
  double b = distance(s.target());
  return a < b ? a : b;
}
double Line::distance(const Line &l) const {
  return intersect(l) ? 0.0 : distance(l.source());
}
bool Line::intersect(const Point &p) const {
  Point v1 = source() - p;
  Point v2 = target() - p;
  return fabs(v2.cross(v1)) < EPS;
}
bool Line::intersect(const Segment &s) const {
  Point v1 = target() - source();
  Point v2 = s.source() - source();
  Point v3 = s.target() - source();
  return v1.cross(v2) * v1.cross(v3) <= EPS;
}
bool Line::intersect(const Line &l) const {
  Point v1 = target() - source();
  Point v2 = l.target() - l.source();
  Point v3 = l.source() - source();
  return fabs(v1.cross(v2)) > EPS || fabs(v1.cross(v3)) < EPS;
}
bool Line::parallel(const Line &l) const {
  double dx = target().x() - source().x();
  double dy = target().y() - source().y();
  double dxl = l.target().x() - l.source().x();
  double dyl = l.target().y() - l.source().y();
  return fabs(dy * dxl - dyl * dx) <= EPS;
}
bool Line::parallel(const Segment &s) const { return parallel(s.line()); }
bool Line::orthogonal(const Line &l) const {
  double dx = target().x() - source().x();
  double dy = target().y() - source().y();
  double dxl = l.target().x() - l.source().x();
  double dyl = l.target().y() - l.source().y();
  return fabs(dy * dyl + dxl * dx) <= EPS;
}
bool Line::orthogonal(const Segment &s) const { return orthogonal(s.line()); }
const Point Line::projection(const Point &p) const {
  Point v1 = p - source();
  Point v2 = source() - target();
  return Point(source() + v2 * (v1.dot(v2) / v2.norm()));
}
const Point Line::reflection(const Point &p) const {
  return p + (projection(p) - p) * 2.0;
}
const Point Line::crosspoint(const Line &l) const {
  Point v1 = target() - source();
  Point v2 = l.target() - l.source();
  Point v3 = target() - l.source();
  double a = v1.cross(v2);
  double b = v1.cross(v3);
  if (fabs(a) <= EPS && fabs(b) <= EPS)
    return l.source();
  return l.source() + v2 * (b / a);
}
POSITION Line::ccw(const Point &p) const { return source().ccw(target(), p); }
void Line::print() const {
  std::cout << "source: ";
  source().print();
  std::cout << "target: ";
  target().print();
}
// Circle
bool Circle::in(const Point &p) const {
  return center().distance(p) < r() - EPS;
}
bool Circle::out(const Point &p) const {
  return r() + EPS < center().distance(p);
}
bool Circle::include(const Point &p) const {
  return center().distance(p) <= r() + EPS;
}
bool Circle::include(const Segment &s) const {
  return center().distance(s) <= r() + EPS;
}
bool Circle::include(const Line &l) const {
  return center().distance(l) <= r() + EPS;
}
bool Circle::include(const Circle &c) const {
  return center().distance(c.center()) <= r() - c.r() + EPS;
}
bool Circle::intersect(const Circle &c) const {
  return center().distance(c.center()) <= r() + c.r() + EPS;
}
std::vector<Point> Circle::crosspoint(const Circle &c) const {
  double angle = atan2(c.y() - y(), c.x() - x());
  double d = center().distance(c.center());
  double add = acos((d * d + r() * r() - c.r() * c.r()) / (2.0 * d * r()));
  std::vector<Point> result;
  result.push_back(
      Point(x() + r() * cos(angle + add), y() + r() * sin(angle + add)));
  result.push_back(
      Point(x() + r() * cos(angle - add), y() + r() * sin(angle - add)));
  return result;
}
void Circle::print() const {
  std::cout << "radius: " << r() << " - point: ";
  center().print();
}
// Polygon
void Polygon::add(const Point &p) { point.push_back(p); }
double Polygon::area() const {
  double sum = 0.0;
  for (int i = 0; i < size(); ++i)
    sum += vertex(i).cross(vertex((i + 1) % size()));
  return fabs(sum) / 2.0;
}
bool Polygon::convex() const {
  POSITION direction = ONLINE_BACK;
  for (int i = 1; i < size(); ++i) {
    POSITION d = vertex(i - 1).ccw(vertex(i), vertex((i + 1) % size()));
    if (d != CLOCKWISE && d != COUNTER_CLOCKWISE)
      continue;
    if (direction == ONLINE_BACK)
      direction = d;
    if (direction != d)
      return false;
  }
  return true;
}
bool Polygon::include(const Point &p) const {
  bool in = false;
  for (int i = 0; i < size(); ++i) {
    Point a = vertex(i) - p;
    Point b = vertex((i + 1) % size()) - p;
    if (a.y() > b.y())
      std::swap(a, b);
    if (a.y() <= 0.0 && 0 < b.y() && a.cross(b) < 0.0)
      in = !in;
    if (fabs(a.cross(b)) <= EPS && a.dot(b) <= EPS)
      return true;
  }
  return in;
}
bool Polygon::intersect(const Polygon &p) const {
  for (const auto &e1 : edge())
    for (const auto &e2 : p.edge())
      if (e1.intersect(e2))
        return true;
  return false;
}
bool Polygon::on_edge(const Point &p) const {
  for (int i = 0; i < size(); ++i)
    if (vertex(i).ccw(vertex((i + 1) % size()), p) == ON_SEGMENT)
      return true;
  return false;
}
const Polygon Polygon::convex_hull() const { // Andrew's Monotone Chain
  Polygon result;
  std::vector<Point> res;
  std::vector<Point> original = vertex();
  sort(original.begin(), original.end());
  original.insert(original.end(), original.rbegin() + 1, original.rend());
  for (const auto &v : original) {
    while (res.size() >= 2 &&
           res[res.size() - 2].ccw(res[res.size() - 1], v) == CLOCKWISE)
      res.pop_back();
    res.push_back(v);
  }
  res.pop_back();
  for (const auto &v : res)
    result.add(v);
  return result;
}
void Polygon::print() const {
  for (const auto &v : vertex())
    std::cout << v.x() << ", " << v.y() << std::endl;
}

////////////////////////////////////////////////////////////////////////////////

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

vector<Circle> C;
vector<vector<int>> edge;
vector<vector<int>> cycle;
vector<int> visited;
void dfs(vector<int> &result) {
  visited[result.back()] = 1;
  for (const auto &v : edge[result.back()]) {
    auto it = find(result.begin(), result.end(), v);
    if (it != result.end()) {
      vector<int> next(it, result.end());
      if (next.size() >= 3)
        cycle.push_back(next);
      continue;
    }
    result.push_back(v);
    dfs(result);
    result.pop_back();
  }
  return;
}

int main() {
  int n, m;
  while (cin >> n >> m, n | m) {
    C = vector<Circle>();
    for (int i = 0; i < n; ++i) {
      double x, y, r;
      cin >> x >> y >> r;
      C.push_back(Circle(x, y, r));
    }

    cycle = vector<vector<int>>();
    visited = vector<int>(n, 0);
    edge = vector<vector<int>>(n);
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        double d = C[i].center().distance(C[j].center());
        if (fabs(C[i].r() - C[j].r()) + EPS < d &&
            d < C[i].r() + C[j].r() - EPS) {
          edge[i].push_back(j);
          edge[j].push_back(i);
        }
      }
    }
    for (int i = 0; i < n; ++i) {
      if (visited[i])
        continue;
      vector<int> v(1, i);
      dfs(v);
    }
    // cout << cycle.size()<<endl;
    // for(int i=0;i<cycle.size();++i){
    //     for(auto&v:cycle[i])cout<<" "<<v;
    //     cout<<endl;
    // }
    // return 0;
    for (int i = 0; i < m; ++i) {
      double x, y;
      cin >> x >> y;
      Point P(x, y);
      cin >> x >> y;
      Point Q(x, y);
      bool yes = true;
      for (const auto &c : C) {
        yes &= (c.in(P) && c.in(Q)) || (c.out(P) && c.out(Q));
        if (!yes)
          break;
      }
      if (i)
        cout << " ";
      if (yes) {
        for (const auto &seq : cycle) {
          bool in = false;
          for (const auto &c : seq)
            in |= C[c].include(P);
          if (in)
            continue;
          Polygon p;
          for (const auto &c : seq)
            p.add(C[c].center());
          bool b1 = p.include(P);
          bool b2 = p.include(Q);
          yes &= (b1 && b2) || (!b1 && !b2);
          if (!yes)
            break;
        }
        cout << (yes ? "YES" : "NO");
      } else {
        cout << "NO";
      }
    }
    cout << endl;
  }
}