#include <cstdio>
#include <iostream>
#include <cmath>
#include <complex>
#include <algorithm>
#include <utility>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

#define EPS 1e-7

typedef complex<double> point;
typedef const point &refpoint;


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

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

double distance_l_p(refpoint a, refpoint b, refpoint c){
	return abs(cross(b - a, c - a)) / abs(b - a);
}

double distance_ls_p(refpoint a, refpoint b, refpoint c){
	if( dot(b - a, c - a) <= 0.0 ) return abs(c - a);
	if( dot(a - b, c - b) <= 0.0 ) return abs(c - b);
	return distance_l_p(a, b, c);
}

bool contains(const vector<point> &plg, refpoint pts){
	int cnt = 0;
	double y = imag(pts);

	for(int i = 0; i < plg.size(); ++i){
		int j = (i + 1 == plg.size() ? 0: i + 1);

		double dyi = imag(plg[i]) - y;
		double dyj = y - imag(plg[j]);
		double tx = (dyi * real(plg[j]) + dyj * real(plg[i])) / (dyi + dyj);

		if(imag(plg[i]) >= y && imag(plg[j]) < y){
			if( tx < real(pts) ) ++cnt;
		}
		else if(imag(plg[i]) < y && imag(plg[j]) >= y){
			if( tx < real(pts) ) --cnt;
		}
	}
	
	return (cnt % 2 != 0);
}

bool intersected(refpoint pa1, refpoint pa2, refpoint pb1, refpoint pb2){
	double a = cross(pa2 - pa1, pb1 - pa1);
	double b = cross(pa2 - pa1, pb2 - pa1);
	double c = cross(pb2 - pb1, pa1 - pb1);
	double d = cross(pb2 - pb1, pa2 - pb1);

	if( (a < -EPS && b > EPS) || (b < -EPS && a > EPS) ){
		if( (c < -EPS && d > EPS) || (d < -EPS && c > EPS) ){
			return true;
		}
	}

	if( 	distance_ls_p(pa1, pa2, pb1) < EPS
		 || distance_ls_p(pa1, pa2, pb2) < EPS
		 || distance_ls_p(pb1, pb2, pa1) < EPS
		 || distance_ls_p(pb1, pb2, pa2) < EPS
	){
		return true;
	}

	return false;
}

bool contact(const vector<point> &plg1, const vector<point> &plg2){
	if( contains(plg1, plg2[0]) || contains(plg2, plg1[0]) ){
		return true;
	}

	int n = plg1.size();
	int m = plg2.size();
	for(int i = 0; i < n; ++i){
		for(int j = 0; j < m; ++j){
			if( intersected(plg1[i], plg1[(i+1)%n], plg2[j], plg2[(j+1)%m]) ){
				return true;
			}
		}
	}
	
	return false;
}


bool ordercomplex(refpoint p1, refpoint p2){
	if( real(p1) != real(p2) )
		return real(p1) < real(p2);
	return imag(p1) < imag(p2);
}


vector<point> convex(vector<point> plg){
	int n = plg.size();
	if( n <= 3 ){
		return plg;
	}

	sort(plg.begin(), plg.end(), ordercomplex);

	vector<point> ret(2 * n);
	int k = 0;

	for(int i = 0; i < n; ++i){
		while( k >= 2 && cross( ret[k-1] - ret[k-2], plg[i] - ret[k-2] ) <= 0.0 ){
			--k;
		}
		ret[k++] = plg[i];
	}

	int t = k + 1;
	for(int i = n - 2; i >= 0; --i){
		while( k >= t && cross( ret[k-1] - ret[k-2], plg[i] - ret[k-2] ) <= 0.0 ){
			--k;
		}
		ret[k++] = plg[i];
	}
	ret.resize(k - 1);
	
	return ret;
}


int main(){
	int n, m;
	double x, y;
	
	while( scanf("%d%d", &n, &m), n != 0 ){
		vector<point> black, white;
		black.reserve(n);
		white.reserve(m);

		for(int i = 0; i < n; ++i){
			scanf("%lf%lf", &x, &y);
			black.push_back( point(x, y) );
		}
		for(int i = 0; i < m; ++i){
			scanf("%lf%lf", &x, &y);
			white.push_back( point(x, y) );
		}


		black = convex(black);
		white = convex(white);

		if( contact(black, white) ){
			puts("NO");
		}
		else{
			puts("YES");
		}

	}
}

Measured memory_bytes: 1232