#include <bits/stdc++.h>

using namespace std;

typedef complex<double> point;
vector<point> pol;
vector<point> pol2;

bool eq(double a, double b) {
  return (fabs(a-b) <= (1e-9));
}

bool lt(double a, double b) {
  return (a - b < -(1e-9));
}

bool on_segment(point a, point b, point c) {
  return eq(abs(b-a), abs(a-c)+abs(b-c));
}

double norm(point v)
{
  return v.real()*v.real() + v.imag()*v.imag();
}
double dot(point a, point b)
{
  return a.real()*b.real() + a.imag()*b.imag();
}
double cross(point a, point b)
{
  return a.real()*b.imag() - a.imag()*b.real();
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE         = -1;
static const int ONLINE_BACK       = 2;
static const int ONLINE_FRONT      = -2;
static const int ON_SEGMENT        = 0;
int ccw(point p0, point p1, point p2)
{
  point a = p1 - p0;
  point b = p2 - p0;
  if(cross(a, b) > 1e-9) return COUNTER_CLOCKWISE;
  if(cross(a, b) < -1e-9) return CLOCKWISE;
  if(dot(a, b) < -1e-9) return ONLINE_BACK;
  if(norm(a) < norm(b)) return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersect(point p1, point p2, point p3, point p4)
{
  return (ccw(p1, p2, p3)*ccw(p1, p2, p4) <= 0 &&
	  ccw(p3, p4, p1)*ccw(p3, p4, p2) <= 0);
}

bool sortY(point p1, point p2)
{
  if(p1.imag() != p2.imag()) return lt(p1.imag(), p2.imag());
  else return lt(p1.real(), p2.real());
}

vector<point> convexHull(vector<point> ps)
{
  int N = ps.size(), j = 0;
  vector<point> pg(N*2);
  
  if(N < 3) return ps;
  
  sort(ps.begin(), ps.end(), sortY);

  for(int i = 0; i < N; i++, j++) {
    while(j >= 2 && ccw(pg[j-2], pg[j-1], ps[i]) == -1) {
      j--;
    }
    pg[j] = ps[i];
  }
  int k = j+1;
  for(int i = N-2; i >= 0; i--, j++) {
    while(j >= k && ccw(pg[j-2], pg[j-1], ps[i]) == -1) {
      j--;
    }
    pg[j] = ps[i];
  }
  pg.resize(j-1);
  return pg;
}

double get_r(point a, point b, point c) 
{
  b -= a, c -= a;
  b *= conj(c);
  return arg(b);
}

int solve(point a)
{
  for(int i = 0; i < (int)pol.size(); i++)
    if(on_segment(pol[i], pol[(i+1)%pol.size()], a)) return 1;
  
  double sum = 0;
  for(int i = 0; i < (int)pol.size(); i++)
    sum += get_r(a, pol[i], pol[(i+1)%pol.size()]);
  
  if(eq(sum, 0)) return 0;
  return 2;
}

int main()
{
  int n, m;
  while(cin >> n >> m, n || m) {
    vector<point> black, white;
    for(int i = 0; i < n; i++) {
      double x, y;
      cin >> x >> y;
      black.push_back(point(x, y));
    }
    pol = convexHull(black);
    for(int i = 0; i < m; i++) {
      double x, y;
      cin >> x >> y;
      white.push_back(point(x, y));
    }
    pol2 = convexHull(white);
    if(n < 2 && m < 2) {
      cout << "YES" << endl;
      continue;
    } else if(n + m == 3) {
      if(n == 2 && ccw(black[0], black[1], white[0]) == ON_SEGMENT ||
	 m == 2 && ccw(white[0], white[1], black[0]) == ON_SEGMENT) {
	cout << "NO" << endl;
      } else {
	cout << "YES" << endl;
      }
      continue;
    } else if(n == 2 && m == 2) {
      if(intersect(black[0], black[1], white[0], white[1])) {
	cout << "NO" << endl;
      } else {
	cout << "YES" << endl;
      }
      continue;
    }
    bool flag = true;
    for(int i = 0; i < 2; i++) {
      if((int)black.size() <= 2) continue;
      for(int j = 0; j < (int)white.size(); j++) {
	if(solve(white[j]) != 0) {
	  flag = false;
	  break;
	}
      }
      swap(pol, pol2);
      swap(black, white);
    }
    cout << (flag ? "YES" : "NO") << endl;
  }
  return 0;
}

Measured memory_bytes: 3256