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

constexpr double EPS = 1e-9;

struct point {
    double x, y;
    point(double x_ = 0.0, double y_ = 0.0):x(x_), y(y_) {}
    point(const point& p):x(p.x), y(p.y) {}

    point operator+ (const point& p) const {
        return point(x + p.x, y + p.y);
    }

    point operator- (const point& p) const {
        return point(x - p.x, y - p.y);
    }

    point operator* (double s) const {
        return point(x * s, y * s);
    }

    point operator* (const point& p) const {
        return point(x * p.x - y * p.y, x * p.y + y * p.x);
    }

    point operator/ (double s) const {
        return point(x / s, y / s);
    }

    bool operator< (const point& p) const {
        return x + EPS < p.x || (abs(x - p.x) < EPS && y + EPS < p.y);
    }

    bool operator== (const point& p) const {
        return abs(x - p.x) < EPS && abs(y - p.y) < EPS;
    }
};

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;
}

struct segment {
    point a, b;
    segment(const point& a_, const point& b_):a(a_), b(b_){}
};

typedef vector<point> polygon;

int ccw(const point& a, point b, point c) {
    b = b - a;
    c = c - a;
    const double tmp = cross(b, c);
    if(tmp > EPS) return 1; // ccw
    if(tmp < -EPS) return -1; // cw
    if(dot(b, c) < 0) return 2; // c, a, b 順に一直線上
    if(norm(b) < norm(c)) return -2; // a, b, c 順に一直線上
    return 0; //a, c, b 順で一直線上
}

bool intersect(const segment& s, const segment& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0
        && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool intersect(const segment& s, const point& p) {
    return ccw(s.a, s.b, p) == 0;
}

polygon convex_hull(vector<point> points) {
    const int n = points.size();
    if(n <= 3) return points;

    sort(points.begin(), points.end());
    int k = 0;
    polygon res;
    res.resize(2 * n);
    for(int i = 0; i < n; res[k++] = points[i++]) {
        while(k >= 2 && ccw(res[k - 2], res[k - 1], points[i]) <= 0) --k;
    }

    const int t = k + 1;
    for(int i = n - 2; i >= 0; res[k++] = points[i--]) {
        while(k >= t && ccw(res[k - 2], res[k - 1], points[i]) <= 0) --k;
    }

    res.resize(k - 1);
    return res;
}

bool intersect(const polygon& P, const point& p) {
    const int n = P.size();
    bool res = false;
    for(int i = 0; i < n; ++i) {
        point v1 = P[i] - p, v2 = P[(i + 1) % n] - p;
        if(v1.y > v2.y) swap(v1, v2);
        if(v1.y < EPS && EPS < v2.y && cross(v1, v2) > EPS) res = !res;
        if(abs(cross(v1, v2)) < EPS && dot(v1, v2) < EPS) return true;
    }

    return res;
}

bool intersect(const polygon& P, const segment& s) {
    const int n = P.size();
    if(intersect(P, s.a) || intersect(P, s.b)) return true;

    for(int i = 0; i < n; ++i) {
        if(intersect(segment(P[i], P[(i + 1) % n]), s)) return true;
    }

    return false;
}

bool intersect(const polygon &a, const polygon &b) {
    const int n = b.size();
    for(int i = 0; i < n; ++i) {
        if(intersect(a, segment(b[i], b[(i + 1) % n]))) return true;
    }

    for(const auto &p : a) {
        if(intersect(b, p)) return true;
    }

    return false;
}

vector<point> input_points(int n) {
    vector<point> res;
    res.reserve(n);

    for(int i = 0; i < n; ++i) {
        double x, y;
        cin >> x >> y;
        res.emplace_back(x, y);
    }

    return res;
}

bool check(const vector<point> &a, const vector<point> &b) {
	return !intersect(convex_hull(a), convex_hull(b));
}

int main() {
    for(int n, m; cin >> n >> m && n;) {
        const auto black_points = input_points(n);
        const auto white_points = input_points(m);
        cout << (check(black_points, white_points) ? "YES" : "NO") << endl;
    }

    return EXIT_SUCCESS;
}

Measured memory_bytes: 1248