#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

#include <complex>
#include <cmath>
#define EPS 1.0e-10
#define PI 3.1415926535897932384 

// 実数の符号関数
inline int signum(double x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
//XY座標
#define X real()
#define Y imag()
// 点
typedef complex<double> P;
 

// 線分・半直線・直線
struct L { P pos, dir; L(P p=P(), P d=P()):pos(p),dir(d){}};

// 多角形
typedef vector<P> G;

// std::norm はabs(p)*abs(p)なので遅い
inline double norm(P p){
	return p.X*p.X+p.Y*p.Y;
}

// 二つのベクトルの内積を計算する
inline double inp(const P& a, const P& b) {
	return (conj(a)*b).X;
}
 
// 二つのベクトルの外積を計算する
inline double outp(const P& a, const P& b) {
	return (conj(a)*b).Y;
}

inline int ccw(const P& p, const P& r, const P& s) {
    P a(r-p), b(s-p);
    int sgn = signum(outp(a, b));
    if (sgn != 0)
        return sgn;
    if (a.X*b.X < -EPS || a.Y*b.Y < -EPS)
        return -1;
    if (norm(a) < norm(b) - EPS)
        return 1;
    return 0;
}

// ベクトルpをベクトルbに射影したベクトルを計算する
inline P proj(const P& p, const P& b) {
	return b*inp(p,b)/norm(b);
}

// 点pから直線lに引いた垂線の足となる点を計算する
inline P perf(const L& l, const P& p) {
	L m(l.pos - p, l.dir);
	return (p + (m.pos - proj(m.pos, m.dir)));
}
bool sp_intersects(const L& s, const P& p) {
    return ( abs(s.pos - p) + abs(s.pos + s.dir - p) - abs(s.dir) < EPS );
}
//(凸とは限らない)多角形の内部に点が包含されているか判定する。
bool gp_contains(const G& g, const P& p) {
    double sum = 0.0;
    int n = g.size();
    if(n && g[0] == p) return true;
    for(int i = 0; i < n; i++) {
        int j = (i+1)%n;
        if (sp_intersects((L){g[i], g[j]-g[i]}, p))
            return true;
        sum += arg((g[j]-p)/(g[i]-p));
    }
    return (abs(sum) > 1);
}

bool xy_less(const P& a, const P& b) {
    if (abs(a.imag()-b.imag()) < EPS) return (a.real() < b.real());
    return (a.imag() < b.imag());
}
template<class IN>
void walk_rightside(IN begin, IN end, vector<P>& v) {
    IN cur = begin;
    v.push_back(*cur++);
    vector<P>::size_type s = v.size();
    v.push_back(*cur++);
    while(cur != end) {
        if (v.size() == s || ccw(v[v.size()-2], v.back(), *cur) > EPS)
            v.push_back(*cur++);
        else
            v.pop_back();
    }
    v.pop_back();
}
//凸包を求める
vector<P> convex_hull(vector<P> v) {
    if (v.size() <= 1)
        return v; // EXCEPTIONAL
    sort(v.begin(), v.end(), xy_less);
    vector<P> cv;
    walk_rightside(v.begin(), v.end(), cv);
    walk_rightside(v.rbegin(), v.rend(), cv);
    return cv;
}
bool ss_intersects(const L& s, const L& t) {
    return (ccw(s.pos, s.pos+s.dir, t.pos) *
            ccw(s.pos, s.pos+s.dir, t.pos+t.dir) <= 0 &&
            ccw(t.pos, t.pos+t.dir, s.pos) *
            ccw(t.pos, t.pos+t.dir, s.pos+s.dir) <= 0);
}
double sp_distance(const L& s, const P& p) {
    const P r = perf(s, p);
    const double pos = ((r-s.pos)/s.dir).real();
    if (-EPS <= pos && pos <= 1 + EPS)
        return abs(r - p);
    return min(abs(s.pos - p),
               abs(s.pos+s.dir - p));
}
double ss_distance(const L& s, const L& t) {
    if (ss_intersects(s, t))
        return 0;
    return min(min(sp_distance(s, t.pos),
            sp_distance(s, t.pos+t.dir)),
            min(sp_distance(t, s.pos),
            sp_distance(t, s.pos+s.dir)));
}
int n, m;

bool check(vector<P> &a, vector<P> &b){
	if(b.size() > 2) REP(i, n) if(gp_contains(b, a[i])) return false;
	if(a.size() > 2) REP(i, m) if(gp_contains(a, b[i])) return false;
	REP(i, n){
		L l1(a[i], a[(i+1)%n] - a[i]);
		REP(j, m){
			L l2(b[j], b[(j+1)%m] - b[j]);
			if(ss_distance(l1, l2) < EPS) return false;
		}
	}
	return true;
}

int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m, n){
		vector<P> a(n), b(m);
		REP(i, n) cin >> a[i].X >> a[i].Y;
		REP(i, m) cin >> b[i].X >> b[i].Y;
		a = convex_hull(a);
		b = convex_hull(b);
		n = a.size(); m = b.size();
		cout << (check(a, b) ? "YES" : "NO") << endl;
	}
	return 0;
}

Measured memory_bytes: 1344