#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <utility>
#include <functional>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
#include <fstream>
using namespace std;
inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v;}
template<class T> inline string toStr(T x) { ostringstream sout; sout << x; return sout.str();}
typedef vector<int> vi;
typedef vector<vi>  vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define REP(i,n) FOR(i,0,(n)-1)
const double EPS = 1e-12;
const double PI = acos(-1.0);
const int INF = INT_MAX/10;

#include <complex>
typedef complex<double> P;

namespace std {
	bool operator< (const P &a, const P &b) {
		return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
	}
}

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

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

int ccw(P a, P b, P c) {
	b -= a; c -= a;
	if(cross(b, c) > 0) return +1;
	if(cross(b, c) < 0) return -1;
	if(dot(b, c) < 0)   return +2;
	if(norm(b) < norm(c)) return -2;
	return 0;
}

vector<P> convex_full(vector<P> ps) {
	int n = ps.size(), k = 0;
	sort(ALL(ps));
	vector<P> ch(2*n);
	for(int i = 0; i < n; ch[k++] = ps[i++])
		while(k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
	for(int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--])
		while(k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
	ch.resize(k-1);
	return ch;
}

enum {OUT, ON, IN};
int convex_contains(const vector<P> &pol, const P &p) {
	const int n = pol.size();
	P g = (pol[0] + pol[n/3] + pol[2*n/3]) / 3.0;
	int a = 0, b = n;
	while(a+1 < b) {
		int c = (a+b)/2;
		if(cross(pol[a]-g, pol[c]-g) > 0) {
			if(cross(pol[a]-g, p-g) > 0 && cross(pol[c]-g, p-g) < 0)
				b = c;
			else
				a = c;
		} else {
			if(cross(pol[a]-g, p-g) < 0 && cross(pol[c]-g, p-g) > 0)
				a = c;
			else
				b = c;
		}
	}
	b %= n;
	if(cross(pol[a]-p, pol[b]-p) < 0) return OUT;
	if(cross(pol[a]-p, pol[b]-p) > 0) return IN;
	return ON;
}

bool is_point_on_ls(P a, P b, P c) {
	return abs(a-c)+abs(c-b) < abs(a-b)+EPS;
}

bool is_intersected_ls(P a1, P a2, P b1, P b2) {
	if((cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < -EPS) &&
	   (cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < -EPS))
	   return true;
	return is_point_on_ls(a1, a2, b1) || is_point_on_ls(a1, a2, b2) ||
		is_point_on_ls(b1, b2, a1) || is_point_on_ls(b1, b2, a2);
}

int main() {
	int n, m;
	while(cin >> n >> m, n) {
		double x, y;
		vector<P> wp, bp;
		REP(i, n) {
			cin >> x >> y;
			wp.push_back(P(x, y));
		}
		REP(i, m) {
			cin >> x >> y;
			bp.push_back(P(x, y));
		}

		int ok = true;
		if(n == 1) {

		} else if(n == 2) {
			REP(i, m) {
				if(is_intersected_ls(wp[0], wp[1], bp[i], bp[(i+1)%m])) {
					ok = false;
					break;
				}
			}
		} else {
			vector<P> wph = convex_full(wp);
			if(wph.size() != 0) {
				REP(i, m) {
					if(convex_contains(wph, bp[i]) != OUT) {
						ok = false;
						break;
					}
				}
			}
		}

		if(m == 1) {

		} else if(m == 2) {
			REP(i, n) {
				if(is_intersected_ls(bp[0], bp[1], wp[i], wp[(i+1)%n])) {
					ok = false;
					break;
				}
			}
		} else {
			vector<P> bph = convex_full(bp);
			if(bph.size() != 0) {
				REP(i, n) {
					if(convex_contains(bph, wp[i]) != OUT) {
						ok = false;
						break;
					}
				}
			}
		}

		cout << (ok ? "YES" : "NO") << endl;
	}

	return 0;
}

Measured memory_bytes: 1256