Problem:
Problem D:
Separate Points
Numbers of black and white points are placed on a plane. Let's imagine that a straight line
of infinite length is drawn on the plane. When the line does not meet any of the points, the
line divides these points into two groups. If the division by such a line results in one group
consisting only of black points and the other consisting only of white points, we say that the
line "separates black and white points".
Let's see examples in Figure 3. In the leftmost example, you can easily find that the black and
white points can be perfectly separated by the dashed line according to their colors. In the
remaining three examples, there exists no such straight line that gives such a separation.
Figure 3: Example planes
In this problem, given a set of points with their colors and positions, you are requested to decide
whether there exists a straight line that separates black and white points.
Input
The input is a sequence of datasets, each of which is formatted as follows.
n m
x
1
y
1
.
.
.
x
n
y
n
x
n
+1
y
n
+1
.
.
.
x
n
+
m
y
n
+
m
The first line contains two positive integers separated by a single space;
n
is the number of black
points, and
m
is the number of white points. They are less than or equal to 100. Then
n
+
m
lines representing the coordinates of points follow. Each line contains two integers
x
i
and
y
i
separated by a space, where (
x
i
,
y
i
) represents the
x
-coordinate and the
y
-coordinate of the
i
-th
point. The color of the
i
-th point is black for 1 ≤ i ≤
n
, and is white for
n
+ 1 ≤
i
≤
n
+
m
.
All the points have integral
x
- and
y
-coordinate values between 0 and 10000 inclusive. You can
also assume that no two points have the same position.
The end of the input is indicated by a line containing two zeros separated by a space.
Output
For each dataset, output "
YES
" if there exists a line satisfying the condition. If not, output
"
NO
". In either case, print it in one line for each input dataset.
Sample Input
3 3
100 700
200 200
600 600
500 100
500 300
800 500
3 3
100 300
400 600
400 100
600 400
500 900
300 300
3 4
300 300
500 300
400 600
100 100
200 900
500 900
800 100
1 2
300 300
100 100
500 500
1 1
100 100
200 100
2 2
0 0
500 700
1000 1400
1500 2100
2 2
0 0
1000 1000
1000 0
0 1000
3 3
0 100
4999 102
10000 103
5001 102
10000 102
0 101
3 3
100 100
200 100
100 200
0 0
400 0
0 400
3 3
2813 1640
2583 2892
2967 1916
541 3562
9298 3686
7443 7921
0 0
Output for the Sample Input
YES
NO
NO
NO
YES
YES
NO
NO
NO
YES

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

ll cross(ll x1, ll y1, ll x2, ll y2) {
    return x1 * y2 - x2 * y1;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m; cin >> n >> m;
    ll inf = 1LL << 25;
    while(n) {
        vector<ll> ax(n), ay(n), bx(m), by(m);
        rep(i, n) cin >> ax[i] >> ay[i];
        rep(i, m) cin >> bx[i] >> by[i];
        bool ok = 0;
        rep(i, n) rep(j, m) {
            ll num = max(abs(ax[i] - bx[j]), abs(ay[i] - by[j]));
            num = inf / num;
            ll X1 = (ax[i] - bx[j]) * num + bx[j];
            ll Y1 = (ay[i] - by[j]) * num + by[j];
            num *= -1;
            ll X2 = (ax[i] - bx[j]) * num + ax[i];
            ll Y2 = (ay[i] - by[j]) * num + ay[i];
            
            // (A - B) * num + B
            // (B - A) * num + B
            assert(cross(ax[i] - X1, ay[i] - Y1, X2 - X1, Y2 - Y1) == 0LL);
            for(ll i1 = -1; i1 <= 1; i1 ++) {
                for(ll i2 = -1; i2 <= 1; i2 ++) {
                    for(ll i3 = -1; i3 <= 1; i3 ++) {
                        for(ll i4 = -1; i4 <= 1; i4 ++) {
                            ll x1 = X1 + i1;
                            ll y1 = Y1 + i2;
                            ll x2 = X2 + i3;
                            ll y2 = Y2 + i4;
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) {
                            //     cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
                            // }
                            {
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }{
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << endl;
                            
                        }
                    }
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
        cin >> n >> m;
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 3480
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

ll cross(ll x1, ll y1, ll x2, ll y2) {
    return x1 * y2 - x2 * y1;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m; cin >> n >> m;
    ll inf = 1LL << 20;
    while(n) {
        vector<ll> ax(n), ay(n), bx(m), by(m);
        rep(i, n) cin >> ax[i] >> ay[i];
        rep(i, m) cin >> bx[i] >> by[i];
        bool ok = 0;
        rep(i, n) rep(j, m) {
            ll num = max(abs(ax[i] - bx[j]), abs(ay[i] - by[j]));
            num = inf / num;
            ll X1 = (ax[i] - bx[j]) * num + ax[i];
            ll Y1 = (ay[i] - by[j]) * num + ay[i];
            num *= -1;
            num --;
            ll X2 = (ax[i] - bx[j]) * num + ax[i];
            ll Y2 = (ay[i] - by[j]) * num + ay[i];
            
            // (A - B) * num + B
            // (B - A) * num + B
            assert(cross(ax[i] - X1, ay[i] - Y1, X2 - X1, Y2 - Y1) == 0LL);
            for(ll i1 = -1; i1 <= 1; i1 ++) {
                for(ll i2 = -1; i2 <= 1; i2 ++) {
                    for(ll i3 = -1; i3 <= 1; i3 ++) {
                        for(ll i4 = -1; i4 <= 1; i4 ++) {
                            ll x1 = X1 + i1;
                            ll y1 = Y1 + i2;
                            ll x2 = X2 + i3;
                            ll y2 = Y2 + i4;
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) {
                            //     cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
                            // }
                            {
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }{
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << endl;
                            
                        }
                    }
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
        cin >> n >> m;
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 610
memory_kb: 3312
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

ll cross(ll x1, ll y1, ll x2, ll y2) {
    return x1 * y2 - x2 * y1;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m; cin >> n >> m;
    ll inf = 1LL << 27;
    while(n) {
        vector<ll> ax(n), ay(n), bx(m), by(m);
        rep(i, n) cin >> ax[i] >> ay[i];
        rep(i, m) cin >> bx[i] >> by[i];
        bool ok = 0;
        rep(i, n) rep(j, m) {
            ll num = max(abs(ax[i] - bx[j]), abs(ay[i] - by[j]));
            num = inf / num;
            ll X1 = (ax[i] - bx[j]) * num + ax[i];
            ll X2 = - (ax[i] - bx[j]) * num + bx[j];
            ll Y1 = (ay[i] - by[j]) * num + ay[i];
            ll Y2 = - (ay[i] - by[j]) * num + by[j];
            
            // (A - B) * num + B
            // (B - A) * num + B
            assert(cross(ax[i] - X1, ay[i] - Y1, X2 - X1, Y2 - Y1) == 0LL);
            for(ll i1 = -1; i1 <= 1; i1 ++) {
                for(ll i2 = -1; i2 <= 1; i2 ++) {
                    for(ll i3 = -1; i3 <= 1; i3 ++) {
                        for(ll i4 = -1; i4 <= 1; i4 ++) {
                            ll x1 = X1 + i1;
                            ll y1 = Y1 + i2;
                            ll x2 = X2 + i3;
                            ll y2 = Y2 + i4;
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) {
                            //     cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
                            // }
                            {
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }{
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << endl;
                            
                        }
                    }
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
        cin >> n >> m;
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 580
memory_kb: 3308
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

ll cross(ll x1, ll y1, ll x2, ll y2) {
    return x1 * y2 - x2 * y1;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m; cin >> n >> m;
    ll inf = 1LL << 28;
    while(n) {
        vector<ll> ax(n), ay(n), bx(m), by(m);
        rep(i, n) cin >> ax[i] >> ay[i];
        rep(i, m) cin >> bx[i] >> by[i];
        bool ok = 0;
        rep(i, n) rep(j, m) {
            ll num = max(abs(ax[i] - bx[j]), abs(ay[i] - by[j]));
            num = inf / num;
            ll X1 = (ax[i] - bx[j]) * num + bx[j];
            ll X2 = - (ax[i] - bx[j]) * num + ax[i];
            ll Y1 = (ay[i] - by[j]) * num + by[j];
            ll Y2 = - (ay[i] - by[j]) * num + ay[i];
            for(ll i1 = -1; i1 <= 1; i1 ++) {
                for(ll i2 = -1; i2 <= 1; i2 ++) {
                    for(ll i3 = -1; i3 <= 1; i3 ++) {
                        for(ll i4 = -1; i4 <= 1; i4 ++) {
                            ll x1 = X1 + i1;
                            ll y1 = Y1 + i2;
                            ll x2 = X2 + i3;
                            ll y2 = Y2 + i4;
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) {
                            //     cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
                            // }
                            {
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }{
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << " ";
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) cout << endl;
                            
                        }
                    }
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
        cin >> n >> m;
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 3384
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

ll cross(ll x1, ll y1, ll x2, ll y2) {
    return x1 * y2 - x2 * y1;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m; cin >> n >> m;
    ll inf = 1LL << 28;
    while(n) {
        vector<ll> ax(n), ay(n), bx(m), by(m);
        rep(i, n) cin >> ax[i] >> ay[i];
        rep(i, m) cin >> bx[i] >> by[i];
        bool ok = 0;
        rep(i, n) rep(j, m) {
            ll num = max(abs(ax[i] - bx[j]), abs(ay[i] - by[j]));
            num = inf / num;
            ll X1 = (ax[i] - bx[j]) * num + bx[j];
            ll X2 = -(ax[i] - bx[j]) * num + ax[i];
            ll Y1 = (ay[i] - by[j]) * num + by[j];
            ll Y2 = -(ay[i] - by[j]) * num + ay[i];
            assert(cross(ax[i] - X1, ay[i] - Y1, X2 - X1, Y2 - Y1) == 0);
            assert(cross(bx[j] - X1, by[j] - Y1, X2 - X1, Y2 - Y1) == 0);
            for(ll i1 = -1; i1 <= 1; i1 ++) {
                for(ll i2 = -1; i2 <= 1; i2 ++) {
                    for(ll i3 = -1; i3 <= 1; i3 ++) {
                        for(ll i4 = -1; i4 <= 1; i4 ++) {
                            ll x1 = X1 + i1;
                            ll y1 = Y1 + i2;
                            ll x2 = X2 + i3;
                            ll y2 = Y2 + i4;
                            // if(i1 == 0 and i2 == 1 and i3 == 0 and i4 == -1) {
                            //     cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
                            // }
                            {
                                bool ng = 0;
                                rep(k, n) {
                                    // if(i == 0 and j == 0 and i1 == -1 and i2 == 0 and i3 == 0 and i4 == -1) cout << ax[k] - x1 << " " << ay[k] - y1 << " " << x2 - x1 << " " << y2 - y1 << " " << cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) << endl;
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    // if(i == 0 and j == 0 and i1 == -1 and i2 == 0 and i3 == 0 and i4 == -1) cout << bx[k] - x1 << " " << by[k] - y1 << " " << x2 - x1 << " " << y2 - y1 << " " << cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) << endl;
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }{
                                bool ng = 0;
                                rep(k, n) {
                                    if(cross(ax[k] - x1, ay[k] - y1, x2 - x1, y2 - y1) >= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) rep(k, m) {
                                    if(cross(bx[k] - x1, by[k] - y1, x2 - x1, y2 - y1) <= 0) {
                                        ng = 1;
                                        break;
                                    }
                                }
                                if(!ng) {
                                    ok = 1;
                                    i = n; j = m;
                                    i1 = 2; i2 = 2; i3 = 2; i4 = 2;
                                    break;
                                }
                            }
                            
                        }
                    }
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
        cin >> n >> m;
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 3396
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

#include <bits/stdc++.h>
using namespace std;

namespace geometry {

using Real = double;
constexpr Real EPS = 1e-7;
constexpr Real PI = numbers::pi;

constexpr int sgn(Real a) { return (a < -EPS) ? -1 : (EPS < a) ? 1 : 0; }

struct Point {
    Real x, y;
    constexpr Point(Real x=0, Real y=0) : x(x), y(y) {}

    constexpr Point& operator += (const Point& rhs) { return x += rhs.x, y += rhs.y, *this; }
    constexpr Point& operator -= (const Point& rhs) { return x -= rhs.x, y -= rhs.y, *this; }
    constexpr Point& operator *= (const Point& rhs) { return *this = Point(x * rhs.x - y * rhs.y, x * rhs.y + y * rhs.x); }
    constexpr Point& operator /= (const Point& rhs) { return *this *= rhs.conj() * rhs.norm2(); }
    constexpr Point& operator *= (Real k) { return x *= k, y *= k, *this; }
    constexpr Point& operator /= (Real k) { return x /= k, y /= k, *this; }

    constexpr Point operator + (const Point& rhs) const { return Point(*this) += rhs; }
    constexpr Point operator - (const Point& rhs) const { return Point(*this) -= rhs; }
    constexpr Point operator * (const Point& rhs) const { return Point(*this) *= rhs; }
    constexpr Point operator / (const Point& rhs) const { return Point(*this) /= rhs; }
    constexpr Point operator * (Real k) const { return Point(*this) *= k; }
    constexpr Point operator / (Real k) const { return Point(*this) /= k; }
    friend constexpr Point operator * (Real k, const Point& p) { return Point(p.x * k, p.y * k); }

    constexpr Point operator - () const { return Point() - *this; }

    constexpr bool operator < (const Point& rhs) const { return sgn(x - rhs.x) ? (x < rhs.x) : (y < rhs.y); }
    constexpr bool operator > (const Point& rhs) const { return rhs < *this; }
    constexpr bool operator == (const Point& rhs) const { return !sgn(x - rhs.x) && !sgn(y - rhs.y); }
    constexpr bool operator != (const Point& rhs) const { return !(*this == rhs); }

    constexpr Real norm2() const { return x * x + y * y; }
    constexpr Real norm() const { return sqrt(norm2()); }
    constexpr Real arg() const { return atan2(y, x); }
    constexpr Point rot(Real theta) const { return Point(x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)); }
    constexpr Point rot90() const { return Point(-y, x); }
    constexpr Point conj() const { return Point(x, -y); }

    friend constexpr Real norm2(const Point& p) { return p.norm2(); }
    friend constexpr Real norm(const Point& p) { return p.norm(); }
    friend constexpr Real arg(const Point& p) { return p.arg(); }
    friend constexpr Point rot(const Point& p, Real theta) { return p.rot(theta); }
    friend constexpr Point rot90(const Point& p) { return p.rot90(); }
    friend constexpr Point conj(const Point& p) { return p.conj(); }

    friend istream& operator >> (istream& is, Point& p) { return is >> p.x >> p.y; }
    friend ostream& operator << (ostream& os, const Point& p) { return os << "(" << p.x << ", " << p.y << ")"; }
};

constexpr Real dot(const Point& a, const Point& b) { return a.x * b.x + a.y * b.y; }
constexpr Real cross(const Point& a, const Point& b) { return a.x * b.y - a.y * b.x; }
constexpr Point polar(Real r, Real theta) { return Point(r * cos(theta), r * sin(theta)); }

// +1 : a - b, a - c : ccw
// -1 : a - b, a - c : cw
// +2 : c - a - b    : on_back
// -2 : a - b - c    : on_front
//  0 : a - c - b    : on_segment
int ccw(const Point& a, Point b, Point c) {
    b -= a, c -= a;
    if(sgn(cross(b, c)) == 1) return 1;
    if(sgn(cross(b, c)) == -1) return -1;
    if(sgn(dot(b, c)) == -1) return 2;
    if(b.norm2() < c.norm2()) return -2;
    return 0; 
}

struct Line {
    Point s, t;
    constexpr Line(Point s=Point(0, 0), Point t=Point(0, 0)) : s(s), t(t) {}
    constexpr Point dir() const { return t - s; }
    constexpr Real norm() const { return dir().norm(); }
    constexpr Point normalize() const { return (t - s) / norm(); }

    friend constexpr Point dir(const Line& l) { return l.dir(); }
    friend constexpr Real norm(const Line& l) { return l.norm(); }
    friend constexpr Point normalize(const Line& l) { return l.normalize(); }
};

Point projection(const Line& l, const Point& p) {
    Real t = dot(p - l.s, l.t - l.s) / norm2(l.t - l.s);
    return l.s + l.dir() * t;
}
Point reflection(const Line& l, const Point& p) {
    Point x = projection(l, p);
    return 2 * x - p;
}

bool is_parallel(const Line& a, const Line& b) { return sgn(cross(a.dir(), b.dir())) == 0; }
bool is_orthogonal(const Line& a, const Line& b) { return sgn(dot(a.dir(), b.dir())) == 0; }
bool is_intersect(const Line& a, const Line& b) { 
    return sgn(ccw(a.s, a.t, b.s)) * sgn(ccw(a.s, a.t, b.t)) <= 0 && sgn(ccw(b.s, b.t, a.s)) * sgn(ccw(b.s, b.t, a.t)) <= 0; 
}

Point cross_ll(const Line& a, const Line& b) {
    Real d1 = cross(a.dir(), b.dir());
    Real d2 = cross(a.dir(), a.t - b.s);
    return b.s + b.dir() * (d2 / d1);
}

Real dist_pp(const Point& a, const Point& b) {
    return norm(a - b);
}
Real dist_lp(const Line& l, const Point& p) {
    return abs(cross(l.dir(), p - l.s)) / norm(l);
}
Real dist_sp(const Line& l, const Point& p) {
    if(sgn(dot(l.dir(), p - l.s)) == -1) return norm(p - l.s);
    if(sgn(dot(-l.dir(), p - l.t)) == -1) return norm(p - l.t);
    return dist_lp(l, p);
}
Real dist_ss(const Line& a, const Line& b) {
    if(is_intersect(a, b)) return 0;
    return min({dist_sp(a, b.s), dist_sp(a, b.t), dist_sp(b, a.s), dist_sp(b, a.t)});
}

struct Polygon : public vector<Point> {
    using vector<Point>::vector;
    Real area() const {
        int sz = size();
        Real ret = 0;
        for(int i = 0; i < sz; i++) {
            ret += cross((*this)[i], (*this)[(i + 1) % sz]);
        }
        return ret / 2;
    }

    bool is_convex() const {
        int sz = size();
        for(int i = 0; i < sz; i++) {
            if(ccw((*this)[i], (*this)[(i + 1) % sz], (*this)[(i + 2) % sz]) == -1) return false;
        }
        return true;
    }

    pair<int, int> diameter() const {
        assert(is_convex());
        int sz = size();
        int right = max_element(begin(), end()) - begin();
        int left = min_element(begin(), end()) - begin();
        Real max_dist = norm2((*this)[left] - (*this)[right]);
        pair<int, int> ret = {left, right};
        for(int i = 0; i < sz; i++) {
            Point pre = (*this)[(left + 1) % sz] - (*this)[left];
            Point nxt = (*this)[right] - (*this)[(right + 1) % sz];
            if(ccw(Point(0, 0), pre, nxt) == 1) left = (left + 1) % sz;
            else right = (right + 1) % sz;
            if(norm2((*this)[left] - (*this)[right]) > max_dist) max_dist = norm2((*this)[left] - (*this)[right]), ret = {left, right};
        }
        return ret;
    }

    friend Real area(const Polygon& pol) { return pol.area(); }
    friend bool is_convex(const Polygon& pol) { return pol.is_convex(); }
    friend pair<int, int> diameter(const Polygon& pol) { return pol.diameter(); } 
};

// 2 : contain
// 1 : on line
// 0 : outside
int contain(const Polygon& pol, const Point& p) {
    bool in = false;
    int sz = pol.size();
    for(int i = 0; i < sz; i++) {
        Point a = pol[i] - p;
        Point b = pol[(i + 1) % sz] - p;
        if(a.y > b.y) swap(a, b);
        if(sgn(a.y) <= 0 && sgn(b.y) == 1 && sgn(cross(a, b)) == -1) in ^= 1;
        if(sgn(cross(a, b)) == 0 && sgn(dot(a, b)) == -1) return 1;
    }
    return 2 * in;
}

Polygon convex_hull(Polygon pol) {
    int sz = pol.size();
    sort(pol.begin(), pol.end());
    Polygon ret;
    for(int i = 0; i < sz; i++) {
        while(ret.size() > 1 && ccw(ret[ret.size() - 2], ret.back(), pol[i]) == -1) ret.pop_back();
        ret.push_back(pol[i]);
    }
    int t = ret.size();
    for(int i = sz - 2; i >= 0; i--) {
        while(ret.size() > t && ccw(ret[ret.size() - 2], ret.back(), pol[i]) == -1) ret.pop_back();
        ret.push_back(pol[i]);
    }
    ret.pop_back();
    return ret;
}

Polygon convex_cut(const Polygon& pol, const Line& l) {
    int sz = pol.size();
    Polygon ret;
    for(int i = 0; i < pol.size(); i++) {
        int t1 = sgn(cross(l.dir(), pol[i] - l.s)), t2 = sgn(cross(l.dir(), pol[(i + 1) % sz] - l.s));
        if(t1 >= 0) ret.push_back(pol[i]); 
        if(t1 * t2 < 0) ret.push_back(cross_ll(Line(pol[i], pol[(i + 1) % sz]), l));
    }
    return ret;
}

Real closest_pair(vector<Point> ps) {
    auto rec = [](auto f, vector<Point>& ps, int l, int r) -> Real {
        if(r - l < 2) return 1e100;
        int mid = (l + r) / 2;
        Real x = ps[mid].x;
        Real d = min(f(f, ps, l, mid), f(f, ps, mid, r));
        auto it = ps.begin(), itl = it + l, itm = it + mid, itr = it + r;
        inplace_merge(itl, itm, itr, [](Point a, Point b) { return a.y < b.y; });
        vector<Point> near_line;
        for(int i = l; i < r; i++) {
            if(abs(ps[i].x - x) >= d) continue;
            int sz = near_line.size();
            for(int j = sz; j--;) {
                if(ps[i].y - near_line[j].y >= d) break;
                d = min(d, dist_pp(ps[i], near_line[j]));
            }
            near_line.push_back(ps[i]);
        }
        return d;
    };
    sort(ps.begin(), ps.end());
    return rec(rec, ps, 0, ps.size());
}

struct Circle {
    Point p;
    Real r;
    Circle() : p(Point(0, 0)), r(0) {}
    Circle(Point p, Real r) : p(p), r(r) {}
};

int intersection(const Circle& c1, const Circle& c2) {
    Real d = dist_pp(c1.p, c2.p);
    if(sgn(d - (c1.r + c2.r)) == 1) return 4;
    if(sgn(d - (c1.r + c2.r)) == 0) return 3;
    if(sgn(d - abs(c1.r - c2.r)) == 1) return 2;
    if(sgn(d - abs(c1.r - c2.r)) == 0) return 1;
    return 0;
}

pair<Point, Point> cross_cl(const Circle& c, const Line& l) {
    Point proj = projection(l, c.p);
    Real h = dist_lp(l, c.p);
    Real d = sqrt(c.r * c.r - h * h);
    Point p1 = proj + l.normalize() * d;
    Point p2 = proj - l.normalize() * d;
    if(dist_pp(p1, l.s) > dist_pp(p2, l.s)) swap(p1, p2);
    return {p1, p2};
}

Circle incircle(const Point& a, const Point& b, const Point& c) {
    Real d1 = dist_pp(b, c);
    Real d2 = dist_pp(c, a);
    Real d3 = dist_pp(a, b);
    Point ip = (a * d1 + b * d2 + c * d3) / (d1 + d2 + d3);
    Real r = dist_lp(Line(a, b), ip);
    return Circle(ip, r);
}

Circle outcircle(const Point& a, const Point& b, const Point& c) {
    Line l1((a + b) / 2, (a + b) / 2 + rot90(b - a));
    Line l2((b + c) / 2, (b + c) / 2 + rot90(c - b));
    Point op = cross_ll(l1, l2);
    Real r = dist_pp(op, a);
    return Circle(op, r);
}

pair<Point, Point> cross_cc(const Circle& c1, const Circle& c2) {
    Real d = dist_pp(c1.p, c2.p);
    Real theta = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    Real phi = arg(c2.p - c1.p);
    Point p1 = c1.p + polar(c1.r, phi - theta);
    Point p2 = c1.p + polar(c1.r, phi + theta);
    if(p1 > p2) swap(p1, p2);
    return {p1, p2};
}

pair<Point, Point> tangent_cp(const Circle& c, const Point& p) {
    return cross_cc(c, Circle(p, sqrt(norm2(c.p - p) - c.r * c.r)));
}

vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
    vector<Line> ret;
    Real d = dist_pp(c1.p, c2.p);
    if(sgn(d) == 0) return {};
    Point u = Line(c1.p, c2.p).normalize();
    Point v = rot90(u);
    for(int s : {-1, 1}) {
        Real h = (c1.r + c2.r * s) / d;
        if(sgn(h * h - 1) == 0) ret.push_back(Line(c1.p + h * u * c1.r, c1.p + h * u * c1.r + v));
        else if(sgn(h * h - 1) == -1) {
            Point U = u * h;
            Point V = v * sqrt(1 - h * h);
            ret.push_back(Line(c1.p + (U + V) * c1.r, c2.p - (U + V) * c2.r * s));
            ret.push_back(Line(c1.p + (U - V) * c1.r, c2.p - (U - V) * c2.r * s));
        } 
    }
    return ret;
}

Real get_angle(const Point& a, const Point& b) {
    return (b * conj(a)).arg();
}

Real common_area_cp(const Circle& c, const Polygon& pol) {
    int sz = pol.size();
    auto cross_area = [&](const Point& a, const Point& b) -> Real {
        Point va = a - c.p, vb = b - c.p;
        Real f = cross(va, vb), ret = 0;
        if(sgn(f) == 0) return 0;
        if(sgn(c.r - max(norm(va), norm(vb))) >= 0) return f;
        if(sgn(dist_sp(Line(a, b), c.p) - c.r) >= 0) return c.r * c.r * get_angle(va, vb);
        auto [cp1, cp2] = cross_cl(c, Line(a, b));
        cp1 -= c.p, cp2 -= c.p;
        if(ccw(va, vb, cp1) != 0) cp1 = cp2;
        if(ccw(va, vb, cp2) != 0) cp2 = cp1;
        ret += (sgn(c.r - norm(va)) >= 0) ? cross(va, cp1) : c.r * c.r * get_angle(va, cp1);
        ret += cross(cp1, cp2);
        ret += (sgn(c.r - norm(vb)) >= 0) ? cross(cp2, vb) : c.r * c.r * get_angle(cp2, vb);
        return ret;
    };
    Real ret = 0;
    for(int i = 0; i < sz; i++) {
        ret += cross_area(pol[i], pol[(i + 1) % sz]);
    }
    return ret * 0.5;
}

Real common_area_cc(const Circle& c1, const Circle& c2) {
    Real d = dist_pp(c1.p, c2.p);
    if(sgn(c1.r + c2.r - d) <= 0) return 0;
    if(sgn(d - abs(c1.r - c2.r)) <= 0) {
        Real r = min(c1.r, c2.r);
        return PI * r * r;
    }
    auto area = [&](const Circle& c1, const Circle& c2) -> Real {
        Real theta = 2 * acos((d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d * c1.r));
        return (theta - sin(theta)) * c1.r * c1.r * 0.5;
    };
    return area(c1, c2) + area(c2, c1);
}

}  // namespace geometry

using namespace geometry;


int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    while(true) {
        int N, M;
        cin >> N >> M;
        if(N == 0) break;
        Polygon black(N), white(M);
        for(int i = 0; i < N; i++) {
            cin >> black[i];
        }
        for(int i = 0; i < M; i++) {
            cin >> white[i];
        }

        auto convex_black = convex_hull(black);
        auto convex_white = convex_hull(white);

        bool yes = true;
        for(int i = 0; i < N; i++) {
            if(contain(convex_white, black[i])) yes = false;
        }
        for(int i = 0; i < M; i++) {
            if(contain(convex_black, white[i])) yes = false;
        }

        for(int i = 0; i < (int)convex_black.size(); i++) {
            for(int j = 0; j < (int)convex_white.size(); j++) {
                Line l1(convex_black[i], convex_black[(i + 1) % convex_black.size()]);
                Line l2(convex_white[j], convex_white[(j + 1) % convex_white.size()]);
                if(is_intersect(l1, l2)) yes = false;
            }
        }

        if(yes) cout << "YES\n";
        else cout << "NO\n";
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(ll i=0;i<n;i++)
#define rep2(i,s,t) for(ll i=s;i<t;i++)
#define all(A) A.begin(),A.end()
using ll=long long;

/*
- `Point p(x, y)` で座標/ベクトルを宣言できる
- `cout << fixed << setprecision(10);` で小数出力の桁数を指定できる
*/

using Real = double;
using Point = complex<Real>;
using Poly = vector<Point>;
Real eps = 1e-6;

int Round(Real x) { return static_cast<int>(round(x)); }

// 同じか判定
bool equal(Point a, Point b) { return abs(a - b) < eps; }

struct Line {
  // 点 a, b を通る直線
  Point a, b;
  Line() = default;
  Line(Point a, Point b) : a(a), b(b) {}
  Line(Real A, Real B, Real C) {
    // 直線の方程式 Ax + By = C;
    if(equal(A, 0)) a = Point(0, C / B), b = Point(1, C / B);
    else if(equal(B, 0)) a = Point(C / A, 0), b = Point(C / A, 1);
    else a = Point(0, C / B), b = Point(C / A, 0);
  }
};

using Segment = Line;

struct Circle {
  Point c; // 中心
  Real r;  // 半径
  Circle() = default;
  Circle(Point c, Real r) : c(c), r(r) {}
};

Real norm(Point p) { return pow(p.real(), 2) + pow(p.imag(), 2); }
// 単位ベクトル
Point unitVector(Point p) { return p / abs(p); }
// 内積(dot product): a・b=|a||b|cosΘ
Real dot(Point a, Point b) { return a.real() * b.real() + a.imag() * b.imag(); }
// 外積(cross product): a×b=|a||b|sinΘ
Real cross(Point a, Point b) {
  return a.real() * b.imag() - a.imag() * b.real();
}
// 点 p を反時計回りに theta(rad) 回転
Point rotate(Point p, Real theta) {
  Real x = cos(theta) * p.real() - sin(theta) * p.imag();
  Real y = sin(theta) * p.real() + cos(theta) * p.imag();
  return {x, y};
}

// 射影(projection): 直線 L に点 p から引いた垂線の足を求める
Point projection(Line L, Point p) {
  Real t = dot(p - L.a, L.a - L.b) / norm(L.a - L.b);
  return L.a + (L.a - L.b) * t;
}

// 反射(reflection): 直線 L を対称軸として点 p と線対称の位置にある点を求める
Point reflection(Line L, Point p) { return p + (projection(L, p) - p) * 2.0; }

int ccw(Point a, Point b, Point c) {
  // a,b,c が反時計回り : 1
  // a,b,c が時計回り : -1
  // c,a,b がこの順で同一直線上 : 2
  // a,b,c がこの順で同一直線上 : -2
  // b,c,a がこの順で同一直線上 : 0
  Point p = b - a;
  Point q = c - a;

  if(cross(p, q) > eps) return 1;
  if(cross(p, q) < -eps) return -1;
  if(dot(p, q) < 0) return 2;
  if(norm(p) < norm(q)) return -2;
  return 0;
}

// 2 直線の直交判定
bool isOrthiogonal(Line L1, Line L2) {
  return equal(dot(L1.b - L1.a, L2.b - L2.a), 0);
}
// 2 直線の平行判定
bool isParallel(Line L1, Line L2) {
  return equal(cross(L1.b - L1.a, L2.b - L2.a), 0);
}
// 線分の交差判定
bool isIntersect(Segment s, Segment t) {
  rep(i, 2) {
    if(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) > 0) return false;
    swap(s, t);
  }
  return true;
}

// 2 直線の交点
Point crossPoint(Line s, Line t) {
  Real d1 = cross(s.b - s.a, t.b - t.a);
  Real d2 = cross(s.b - s.a, s.b - t.a);
  if(equal(abs(d1), 0.0) && equal(abs(d2), 0.0)) return t.a;
  return t.a + (t.b - t.a) * (d2 / d1);
}

// 直線 L と点 p の距離
Real distLinePoint(Line L, Point p) {
  return abs(cross(L.b - L.a, p - L.a)) / abs(L.b - L.a);
}
// 線分 L と点 p の距離
Real distSegPoint(Segment L, Point p) {
  if(dot(L.b - L.a, p - L.a) < eps) return abs(p - L.a);
  if(dot(L.a - L.b, p - L.b) < eps) return abs(p - L.b);
  return abs(cross(L.b - L.a, p - L.a)) / abs(L.b - L.a);
}
// 線分同士の距離
Real distSegSeg(Segment s, Segment t) {
  if(isIntersect(s, t)) return 0;
  Real d = distSegPoint(s, t.a);
  d = min(d, distSegPoint(s, t.b));
  d = min(d, distSegPoint(t, s.a));
  d = min(d, distSegPoint(t, s.b));
  return d;
}

// 多角形の面積
Real PolyArea(Poly p) {
  int n = p.size();
  Real res = 0;
  rep(i, n) { res += cross(p[i], p[(i + 1) % n]); }
  return res / 2;
}

// 凸判定
bool isConvex(Poly p) {
  int n = p.size();
  rep(i, n) {
    if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) == -1) return false;
  }
  return true;
}

// 凸包
Poly ConvexHull(Poly p) {
  int n = p.size();
  if(n <= 2) return p;
  sort(all(p), [&](Point a, Point b) {
    return !equal(real(a), real(b)) ? real(a) < real(b) : imag(a) < imag(b);
  });
  int sz = 0;
  Poly CH(2 * n);
  rep(i, n) {
    // 同一直線上の3点を含める -> (<-eps), 含めない -> (<eps)
    while(sz > 1 && cross(CH[sz - 1] - CH[sz - 2], p[i] - CH[sz - 1]) < -eps)
      sz--;
    CH[sz] = p[i];
    sz++;
  }
  int t = sz;
  for(int i = n - 2; i >= 0; i--) {
    while(sz > t && cross(CH[sz - 1] - CH[sz - 2], p[i] - CH[sz - 1]) < -eps)
      sz--;
    CH[sz] = p[i];
    sz++;
  }
  CH.resize(sz - 1);
  return CH;
}

// 多角形 g に点 p が含まれるか? 含む:2, 辺上:1, 含まない:0
int isContain(Poly g, Point p) {
  int IN = 0;
  int n = g.size();
  rep(i, n) {
    Point a = g[i] - p;
    Point b = g[(i + 1) % n] - p;
    if(a.imag() > b.imag()) swap(a, b);
    if(imag(a) < eps && eps < imag(b) && cross(a, b) < -eps) IN ^= 1;
    if(equal(cross(a, b), 0) && dot(a, b) < eps) return 1;
  }
  return 2 * IN;
}

// 凸多角形の直径(最遠頂点対間距離)
Real ConvexDiametar(Poly p) {
  int n = p.size();
  int i0 = 0, j0 = 0;
  rep2(i, 1, n) {
    if(imag(p[i]) > imag(p[i0])) i0 = i;
    if(imag(p[i]) < imag(p[j0])) j0 = i;
  }
  Real mx = abs(p[i0] - p[j0]);
  int i = i0, j = j0;
  while(i != j0 || j != i0) {
    if(cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) >= 0)
      j = (j + 1) % n;
    else i = (i + 1) % n;
    mx = max(mx, abs(p[i] - p[j]));
  }
  return mx;
}

// 凸多角形の切断: 直線 L.a -> L.b で切断して，その左側の凸多角形を返す
Poly ConvexCut(Poly p, Line L) {
  Poly res;
  int n = p.size();
  rep(i, n) {
    Point now = p[i], nxt = p[(i + 1) % n];
    if(ccw(L.a, L.b, now) != -1) res.push_back(now);
    if(ccw(L.a, L.b, now) * ccw(L.a, L.b, nxt) < 0)
      res.push_back(crossPoint(Line(now, nxt), L));
  }
  return res;
}

int IsIntersectCircle(Circle c1, Circle c2) {
  Real d = abs(c1.c - c2.c);
  if(d > c1.r + c2.r + eps) return 4;      // 2 円が離れている
  if(equal(d, c1.r + c2.r)) return 3;      // 外接
  if(equal(d, abs(c1.r - c2.r))) return 1; // 内接
  if(d < abs(c1.r - c2.r) - eps) return 0; // 内包
  return 2;                                // 2 交点を持つ
}

// 三角形の内接円
Circle InscribedCircle(Point a, Point b, Point c) {
  Real A = abs(b - c), B = abs(c - a), C = abs(b - a);
  Point p(A * real(a) + B * real(b) + C * real(c),
          A * imag(a) + B * imag(b) + C * imag(c));
  p /= (A + B + C);
  Real r = distLinePoint(Line(a, b), p);
  return Circle(p, r);
}

// 三角形の外接円
Circle CircumscribedCircle(Point a, Point b, Point c) {
  Point p = (a - b) * norm(c) + (b - c) * norm(a) + (c - a) * norm(b);
  p /= (a - b) * conj(c) + (b - c) * conj(a) + (c - a) * conj(b);
  Real r = abs(p - a);
  return Circle(p, r);
}

// 円 C と直線Lの交点
vector<Point> CrossPointCircleLine(Circle C, Line L) {
  Real d = distLinePoint(L, C.c);
  if(d > C.r + eps) return {};
  Point h = projection(L, C.c);
  if(abs(d - C.r) < eps) return {h};
  Point e = unitVector(L.b - L.a);
  Real ph = sqrt(C.r * C.r - d * d);
  return {h - e * ph, h + e * ph};
}

// 2 円の交点
vector<Point> CrossPointCircles(Circle C1, Circle C2) {
  int t = IsIntersectCircle(C1, C2);
  Real d = abs(C1.c - C2.c);
  if(t == 4 || t == 0) return {};
  if(t == 3) return {C1.c + (C2.c - C1.c) * (C1.r / (C1.r + C2.r))};
  if(t == 1) {
    if(C2.r < C1.r - eps) return {C1.c + (C2.c - C1.c) * (C1.r / d)};
    else return {C2.c + (C1.c - C2.c) * (C2.r / d)};
  }
  Real rc1 = (C1.r * C1.r + d * d - C2.r * C2.r) / (2 * d);
  Real rs1 = sqrt(C1.r * C1.r - rc1 * rc1);
  if(C1.r - abs(rc1) < eps) rs1 = 0;
  Point e12 = unitVector(C2.c - C1.c);
  return {C1.c + rc1 * e12 + rs1 * e12 * Point(0, 1),
          C1.c + rc1 * e12 + rs1 * e12 * Point(0, -1)};
}

// 点 p を通る円 c の接線
vector<Point> tangentToCircle(Point p, Circle C) {
  return CrossPointCircles(C, Circle(p, sqrt(norm(C.c - p) - C.r * C.r)));
}

Real intersection_area(Circle c1, Circle c2) {
  Real d = abs(c1.c - c2.c);
  if (d > c1.r + c2.r - eps) return 0;
  if (abs(c1.r - c2.r) >= d - eps) return pow(min(c1.r, c2.r), 2) * M_PI;
  Real rd = c1.r * c1.r - c2.r * c2.r;
  long double cos1 = (d * d + rd) / (2 * d * c1.r);
  long double cos2 = (d * d - rd) / (2 * d * c2.r);
  Real ans1 = c1.r * c1.r * (acosl(cos1) - cos1 * sqrtl(1 - cos1 * cos1));
  Real ans2 = c2.r * c2.r * (acosl(cos2) - cos2 * sqrtl(1 - cos2 * cos2));
  return ans1 + ans2;
}

bool in_circle(Circle c, Point p) { return abs(c.c - p) < c.r + eps; }

Circle c2(Point a, Point b) {
  return Circle((a + b) / (Real)2.0, abs(a - b) / (Real)2.0);
}

// 最小包含円
Circle smallest_enclosing_disc(vector<Point> p) {
  if (p.size() == 1) {
    return {p[0], 0};
  }
  mt19937 rng(2024);
  int sz = p.size();
  shuffle(p.begin(), p.end(), rng);
  Circle c = c2(p[0], p[1]);
  rep2(i, 2, sz) {
    if (!in_circle(c, p[i])) {
      c = c2(p[0], p[i]);
      rep2(j, 1, i) {
        if (!in_circle(c, p[j])) {
          c = c2(p[i], p[j]);
          rep(k, j) {
            if (!in_circle(c, p[k])) {
              c = CircumscribedCircle(p[i], p[j], p[k]);
            }
          }
        }
      }
    }
  }
  return c;
}


void solve(int n,int m){
    Poly A(n),B(m);
    rep(i,n){
        double x,y;
        cin>>x>>y;
        A[i]=Point(x,y);
    }
    rep(i,m){
        double x,y;
        cin>>x>>y;
        B[i]=Point(x,y);
    }
    Poly CA=ConvexHull(A);
    Poly CB=ConvexHull(B);
    bool OK=1;
    for(auto p:CA)if(isContain(CB,p))OK=0;
    for(auto p:CB)if(isContain(CA,p))OK=0;
    int an=CA.size(),bn=CB.size();
    rep(i,an)rep(j,bn){
        Segment U(CA[i],CA[(i+1)%an]);
        Segment V(CB[j],CB[(j+1)%bn]);
        if(isIntersect(U,V))OK=0;
    }
    cout<<(OK?"YES":"NO")<<"\n";
}

int main(){
    
    cin.tie(nullptr);
    ios::sync_with_stdio(false);


    int n,m;
    while(cin>>n>>m){
        if(n+m==0)return 0;
        solve(n,m);
    }
    
}
accuracy: 1
time_ms: 10
memory_kb: 3568
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

using T = double;
const T eps = 1e-12;
using Point = complex<T>;
using Poly = vector<Point>;
#define X real()
#define Y imag()
template <typename T> inline bool eq(const T &a, const T &b) {
    return fabs(a - b) < eps;
}
bool cmp(const Point &a, const Point &b) {
    auto sub = [&](Point a) {
        return (a.Y < 0 ? -1 : (a.Y == 0 && a.X >= 0 ? 0 : 1));
    };
    if (sub(a) != sub(b))
        return sub(a) < sub(b);
    return a.Y * b.X < a.X * b.Y;
}
struct Line {
    Point a, b, dir;
    Line() {}
    Line(Point _a, Point _b) : a(_a), b(_b), dir(b - a) {}
    Line(T A, T B, T C) {
        if (eq(A, .0)) {
            a = Point(0, C / B), b = Point(1 / C / B);
        } else if (eq(B, .0)) {
            a = Point(C / A, 0), b = Point(C / A, 1);
        } else {
            a = Point(0, C / B), b = Point(C / A, 0);
        }
    }
};
struct Segment : Line {
    Segment() {}
    Segment(Point _a, Point _b) : Line(_a, _b) {}
};
struct Circle {
    Point p;
    T r;
    Circle() {}
    Circle(Point _p, T _r) : p(_p), r(_r) {}
};

istream &operator>>(istream &is, Point &p) {
    T x, y;
    is >> x >> y;
    p = Point(x, y);
    return is;
}
ostream &operator<<(ostream &os, Point &p) {
    os << fixed << setprecision(12) << p.X << ' ' << p.Y;
    return os;
}
Point unit(const Point &a) {
    return a / abs(a);
}
T dot(const Point &a, const Point &b) {
    return a.X * b.X + a.Y * b.Y;
}
T cross(const Point &a, const Point &b) {
    return a.X * b.Y - a.Y * b.X;
}
Point rot(const Point &a, const T &theta) {
    return Point(cos(theta) * a.X - sin(theta) * a.Y,
                 sin(theta) * a.X + cos(theta) * a.Y);
}
Point rot90(const Point &a) {
    return Point(-a.Y, a.X);
}
T arg(const Point &a, const Point &b, const Point &c) {
    double ret = acos(dot(a - b, c - b) / abs(a - b) / abs(c - b));
    if (cross(a - b, c - b) < 0)
        ret = -ret;
    return ret;
}

Point Projection(const Line &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Projection(const Segment &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Reflection(const Line &l, const Point &p) {
    return p + (Projection(l, p) - p) * 2.;
}
int ccw(const Point &a, Point b, Point c) {
    b -= a;
    c -= a;
    if (cross(b, c) > eps)
        return 1; // ccw

    if (cross(b, c) < -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 isOrthogonal(const Line &a, const Line &b) {
    return eq(dot(a.b - a.a, b.b - b.a), .0);
}
bool isParallel(const Line &a, const Line &b) {
    return eq(cross(a.b - a.a, b.b - b.a), .0);
}
bool isIntersect(const Segment &a, const Segment &b) {
    return ccw(a.a, a.b, b.a) * ccw(a.a, a.b, b.b) <= 0 and
           ccw(b.a, b.b, a.a) * ccw(b.a, b.b, a.b) <= 0;
}
int isIntersect(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d > a.r + b.r + eps)
        return 4;
    if (eq(d, a.r + b.r))
        return 3;
    if (eq(d, abs(a.r - b.r)))
        return 1;
    if (d < abs(a.r - b.r) - eps)
        return 0;
    return 2;
}
T Dist(const Line &a, const Point &b) {
    Point c = Projection(a, b);
    return abs(c - b);
}
T Dist(const Segment &a, const Point &b) {
    if (dot(a.b - a.a, b - a.a) < eps)
        return abs(b - a.a);
    if (dot(a.a - a.b, b - a.b) < eps)
        return abs(b - a.b);
    return abs(cross(a.b - a.a, b - a.a)) / abs(a.b - a.a);
}
T Dist(const Segment &a, const Segment &b) {
    if (isIntersect(a, b))
        return .0;
    T res = min({Dist(a, b.a), Dist(a, b.b), Dist(b, a.a), Dist(b, a.b)});
    return res;
}
Point Intersection(const Line &a, const Line &b) {
    T d1 = cross(a.b - a.a, b.b - b.a);
    T d2 = cross(a.b - a.a, a.b - b.a);
    if (eq(d1, 0.) and eq(d2, 0.))
        return b.a;
    return b.a + (b.b - b.a) * (d2 / d1);
}
Poly Intersection(const Circle &a, const Line &b) {
    Poly res;
    T d = Dist(b, a.p);
    if (d > a.r + eps)
        return res;
    Point h = Projection(b, a.p);
    if (eq(d, a.r)) {
        res.push_back(h);
        return res;
    }
    Point e = unit(b.b - b.a);
    T ph = sqrt(a.r * a.r - d * d);
    res.push_back(h - e * ph);
    res.push_back(h + e * ph);
    return res;
}
Poly Intersection(const Circle &a, const Segment &b) {
    Line c(b.a, b.b);
    Poly sub = Intersection(a, c);
    double xmi = min(b.a.X, b.b.X), xma = max(b.a.X, b.b.X);
    double ymi = min(b.a.Y, b.b.Y), yma = max(b.a.Y, b.b.Y);
    Poly res;
    rep(i, 0, sub.size()) {
        if (xmi <= sub[i].X + eps and sub[i].X - eps <= xma and
            ymi <= sub[i].Y + eps and sub[i].Y - eps <= yma) {
            res.push_back(sub[i]);
        }
    }
    return res;
}
Poly Intersection(const Circle &a, const Circle &b) {
    Poly res;
    int mode = isIntersect(a, b);
    T d = abs(a.p - b.p);
    if (mode == 4 or mode == 0)
        return res;
    if (mode == 3) {
        T t = a.r / (a.r + b.r);
        res.push_back(a.p + (b.p - a.p) * t);
        return res;
    }
    if (mode == 1) {
        if (b.r < a.r - eps) {
            res.push_back(a.p + (b.p - a.p) * (a.r / d));
        } else {
            res.push_back(b.p + (a.p - b.p) * (b.r / d));
        }
        return res;
    }
    T rc = (a.r * a.r + d * d - b.r * b.r) / d / 2.;
    T rs = sqrt(a.r * a.r - rc * rc);
    if (a.r - abs(rc) < eps)
        rs = 0;
    Point e = unit(b.p - a.p);
    res.push_back(a.p + rc * e + rs * e * Point(0, 1));
    res.push_back(a.p + rc * e + rs * e * Point(0, -1));
    return res;
}
Poly HalfplaneIntersection(vector<Line> &H) {
    sort(ALL(H), [&](Line &l1, Line &l2) { return cmp(l1.dir, l2.dir); });
    auto outside = [&](Line &L, Point p) -> bool {
        return cross(L.dir, p - L.a) < -eps;
    };
    deque<Line> deq;
    int sz = 0;
    rep(i, 0, SZ(H)) {
        while (sz > 1 and
               outside(H[i], Intersection(deq[sz - 1], deq[sz - 2]))) {
            deq.pop_back();
            sz--;
        }
        while (sz > 1 and outside(H[i], Intersection(deq[0], deq[1]))) {
            deq.pop_front();
            sz--;
        }
        if (sz > 0 and fabs(cross(H[i].dir, deq[sz - 1].dir)) < eps) {
            if (dot(H[i].dir, deq[sz - 1].dir) < 0) {
                return {};
            }
            if (outside(H[i], deq[sz - 1].a)) {
                deq.pop_back();
                sz--;
            } else
                continue;
        }
        deq.push_back(H[i]);
        sz++;
    }

    while (sz > 2 and outside(deq[0], Intersection(deq[sz - 1], deq[sz - 2]))) {
        deq.pop_back();
        sz--;
    }
    while (sz > 2 and outside(deq[sz - 1], Intersection(deq[0], deq[1]))) {
        deq.pop_front();
        sz--;
    }
    if (sz < 3)
        return {};
    deq.push_back(deq.front());
    Poly ret;
    rep(i, 0, sz) ret.push_back(Intersection(deq[i], deq[i + 1]));
    return ret;
}

T Area(const Poly &a) {
    T res = 0;
    int n = a.size();
    rep(i, 0, n) res += cross(a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Poly &a, const Circle &b) {
    int n = a.size();
    if (n < 3)
        return .0;
    auto rec = [&](auto self, const Circle &c, const Point &p1,
                   const Point &p2) {
        Point va = c.p - p1, vb = c.p - p2;
        T f = cross(va, vb), res = .0;
        if (eq(f, .0))
            return res;
        if (max(abs(va), abs(vb)) < c.r + eps)
            return f;
        if (Dist(Segment(p1, p2), c.p) > c.r - eps)
            return c.r * c.r * arg(vb * conj(va));
        auto u = Intersection(c, Segment(p1, p2));
        Poly sub;
        sub.push_back(p1);
        for (auto &x : u)
            sub.push_back(x);
        sub.push_back(p2);
        rep(i, 0, sub.size() - 1) res += self(self, c, sub[i], sub[i + 1]);
        return res;
    };
    T res = .0;
    rep(i, 0, n) res += rec(rec, b, a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d >= a.r + b.r - eps)
        return .0;
    if (d <= abs(a.r - b.r) + eps) {
        T r = min(a.r, b.r);
        return M_PI * r * r;
    }
    T ath = acos((a.r * a.r + d * d - b.r * b.r) / d / a.r / 2.);
    T res = a.r * a.r * (ath - sin(ath * 2) / 2.);
    T bth = acos((b.r * b.r + d * d - a.r * a.r) / d / b.r / 2.);
    res += b.r * b.r * (bth - sin(bth * 2) / 2.);
    return fabs(res);
}
bool isConvex(const Poly &a) {
    int n = a.size();
    int cur, pre, nxt;
    rep(i, 0, n) {
        pre = (i - 1 + n) % n;
        nxt = (i + 1) % n;
        cur = i;
        if (ccw(a[pre], a[cur], a[nxt]) == -1)
            return 0;
    }
    return 1;
}
int isContained(const Poly &a,
                const Point &b) { // 0:not contain,1:on edge,2:contain

    bool res = 0;
    int n = a.size();
    rep(i, 0, n) {
        Point p = a[i] - b, q = a[(i + 1) % n] - b;
        if (p.Y > q.Y)
            swap(p, q);
        if (p.Y < eps and eps < q.Y and cross(p, q) > eps)
            res ^= 1;
        if (eq(cross(p, q), .0) and dot(p, q) < eps)
            return 1;
    }
    return (res ? 2 : 0);
}
Poly ConvexHull(Poly &a) {
    sort(ALL(a), [](const Point &p, const Point &q) {
        return (eq(p.Y, q.Y) ? p.X < q.X : p.Y < q.Y);
    });
    a.erase(unique(ALL(a)), a.end());
    int n = a.size(), k = 0;
    Poly res(n * 2);
    for (int i = 0; i < n; res[k++] = a[i++]) {
        while (k >= 2 and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    for (int i = n - 2, t = k + 1; i >= 0; res[k++] = a[i--]) {
        while (k >= t and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    res.resize(k - 1);
    return res;
}
T Diam(const Poly &a) {
    int n = a.size();
    int x = 0, y = 0;
    rep(i, 1, n) {
        if (a[i].Y > a[x].Y)
            x = i;
        if (a[i].Y < a[y].Y)
            y = i;
    }
    T res = abs(a[x] - a[y]);
    int i = x, j = y;
    do {
        if (cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j]) < 0)
            i = (i + 1) % n;
        else
            j = (j + 1) % n;
        chmax(res, abs(a[i] - a[j]));
    } while (i != x or j != y);
    return res;
}
Poly Cut(const Poly &a, const Line &l) {
    int n = a.size();
    Poly res;
    rep(i, 0, n) {
        Point p = a[i], q = a[(i + 1) % n];
        if (ccw(l.a, l.b, p) != -1)
            res.push_back(p);
        if (ccw(l.a, l.b, p) * ccw(l.a, l.b, q) < 0)
            res.push_back(Intersection(Line(p, q), l));
    }
    return res;
}

T Closest(Poly &a) {
    int n = a.size();
    if (n <= 1)
        return 0;
    sort(ALL(a), [&](Point a, Point b) {
        return (eq(a.X, b.X) ? a.Y < b.Y : a.X < b.X);
    });
    Poly buf(n);
    auto rec = [&](auto self, int lb, int rb) -> T {
        if (rb - lb <= 1)
            return (T)INF;
        int mid = (lb + rb) >> 1;
        auto x = a[mid].X;
        T res = min(self(self, lb, mid), self(self, mid, rb));
        inplace_merge(a.begin() + lb, a.begin() + mid, a.begin() + rb,
                      [&](auto p, auto q) { return p.Y < q.Y; });
        int ptr = 0;
        rep(i, lb, rb) {
            if (abs(a[i].X - x) >= res)
                continue;
            rep(j, 0, ptr) {
                auto sub = a[i] - buf[ptr - 1 - j];
                if (sub.Y >= res)
                    break;
                chmin(res, abs(sub));
            }
            buf[ptr++] = a[i];
        }
        return res;
    };
    return rec(rec, 0, n);
}

Circle Incircle(const Point &a, const Point &b, const Point &c) {
    T A = abs(b - c), B = abs(c - a), C = abs(a - b);
    Point p(A * a.X + B * b.X + C * c.X, A * a.Y + B * b.Y + C * c.Y);
    p /= (A + B + C);
    T r = Dist(Line(a, b), p);
    return Circle(p, r);
}
Circle Circumcircle(const Point &a, const Point &b, const Point &c) {
    Line l1((a + b) / 2., (a + b) / 2. + (b - a) * Point(0, 1));
    Line l2((b + c) / 2., (b + c) / 2. + (c - b) * Point(0, 1));
    Point p = Intersection(l1, l2);
    return Circle(p, abs(p - a));
}
Poly tangent(const Point &a, const Circle &b) {
    return Intersection(b, Circle(a, sqrt(norm(b.p - a) - b.r * b.r)));
}
vector<Line> tangent(const Circle &a, const Circle &b) {
    vector<Line> res;
    T d = abs(a.p - b.p);
    if (eq(d, 0.))
        return res;
    Point u = unit(b.p - a.p);
    Point v = u * Point(0, 1);
    for (int t : {-1, 1}) {
        T h = (a.r + b.r * t) / d;
        if (eq(h * h, 1.)) {
            res.push_back(Line(a.p + (h > 0 ? u : -u) * a.r,
                               a.p + (h > 0 ? u : -u) * a.r + v));
        } else if (1 > h * h) {
            Point U = u * h, V = v * sqrt(1 - h * h);
            res.push_back(Line(a.p + (U + V) * a.r, b.p - (U + V) * (b.r * t)));
            res.push_back(Line(a.p + (U - V) * a.r, b.p - (U - V) * (b.r * t)));
        }
    }
    return res;
}

/**
 * @brief Geometry
 */

int main() {
while(1) {
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0) return 0;
    Poly A(N), B(M);
    rep(i,0,N) {
        double x, y;
        cin >> x >> y;
        A[i] = Point(x,y);
    }
    rep(i,0,M) {
        double x, y;
        cin >> x >> y;
        B[i] = Point(x,y);
    }
    if (A.size() >= 2) A = ConvexHull(A);
    if (B.size() >= 2) B = ConvexHull(B);
    bool check = true;
    rep(i,0,A.size()) {
        rep(j,0,B.size()) {
            if (isIntersect(Segment(A[i],A[(i+1)%(int)A.size()]),Segment(B[j],B[(j+1)%(int)B.size()]))) check = false;
        }
    }
    rep(i,0,A.size()) {
        if (isContained(B,A[i])) check = false;
    }
    rep(i,0,B.size()) {
        if (isContained(A,B[i])) check = false;
    }
    cout << (check ? "YES" : "NO") << endl;
}
}
accuracy: 1
time_ms: 10
memory_kb: 3432
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Point {
  int x, y, color;
  Point operator-(const Point p) const { return {x - p.x, y - p.y, color}; }
  int cross(const Point p) const { return x * p.y - y * p.x; }
  int half() const { return !(y > 0 || (y == 0 && x > 0)); }
  Point to_first_half() const {
    if (half() == 0) return *this;
    return {-x, -y, color};
  }
};

bool cmp(const Point p, const Point q) {
  return p.to_first_half().cross(q.to_first_half()) > 0;
}

bool possible_aux(const vector<Point>& points) {
  int counts[2][2] = {{0, 0}, {0, 0}};

  for (const Point p : points) {
    counts[p.half()][p.color]++;
  }

  const auto ok = [&]() -> bool {
    return (counts[1][0] == 0 && counts[0][1] == 0) ||
           (counts[0][0] == 0 && counts[1][1] == 0);
  };

  if (ok()) return true;

  for (int i = 0; i < (int)points.size(); i++) {
    const Point p = points[i];
    const Point q = points[(i + 1) % points.size()];

    counts[!p.half()][p.color]++;
    counts[p.half()][p.color]--;

    if (p.cross(q) != 0 && ok()) return true;
  }

  return false;
}

bool possible(vector<Point> points) {
  for (int i = 0; i < (int)points.size(); i++) {
    vector<Point> centered;
    for (int j = 0; j < (int)points.size(); j++) {
      if (i == j) continue;
      centered.push_back(points[j] - points[i]);
    }
    sort(centered.begin(), centered.end(), cmp);
    if (possible_aux(centered)) return true;
  }

  return false;
}

int main() {
  int n, m;

  while (cin >> n >> m && n && m) {
    vector<Point> points(n + m);
    for (int i = 0; i < n + m; i++) {
      auto& p = points[i];
      cin >> p.x >> p.y;
      p.color = i < n;
    }

    cout << (possible(points) ? "YES" : "NO") << endl;
  }
}
accuracy: 1
time_ms: 300
memory_kb: 3360
final_rank: 7

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
//vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
template<typename T> vector<T> inv_perm(const vector<T>&ord){
  vector<T>inv(ord.size());
  for(int i=0;i<ord.size();i++)inv[ord[i]] = i;
  return inv;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
ll modulo(ll n,ll d){return (n%d+d)%d;};
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}

template <typename F>
class
#if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
  [[nodiscard]]
#endif  // defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard)
FixPoint final : private F
{
public:
  template <typename G>
  explicit constexpr FixPoint(G&& g) noexcept
    : F{std::forward<G>(g)}
  {}

  template <typename... Args>
  constexpr decltype(auto)
  operator()(Args&&... args) const
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
  noexcept(noexcept(F::operator()(std::declval<FixPoint>(), std::declval<Args>()...)))
#endif  // !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 9
  {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};  // class FixPoint


#if defined(__cpp_deduction_guides)
template <typename F>
FixPoint(F&&)
-> FixPoint<std::decay_t<F>>;
#endif  // defined(__cpp_deduction_guides)


namespace
{
  template <typename F>
#if !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
  #  if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
  __attribute__((warn_unused_result))
#  elif defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_Check_return_)
  _Check_return_
#  endif  // defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#endif  // !defined(__has_cpp_attribute) || !__has_cpp_attribute(nodiscard)
  inline constexpr decltype(auto)
  makeFixPoint(F&& f) noexcept
  {
    return FixPoint<std::decay_t<F>>{std::forward<std::decay_t<F>>(f)};
  }
}  // namespace

using Real = long double;
using Point = complex<Real>;
const Real EPS = 1e-10, PI = acos((Real)(-1.0));

inline bool eq(Real a, Real b) { return fabs(b - a) < EPS; }
inline bool eq(Point a, Point b) { return fabs(b - a) < EPS; }

Point operator*(const Point &p, const Real &d) {
  return Point(real(p) * d, imag(p) * d);
}

istream &operator>>(istream &is, Point &p) {
  Real a, b;
  is >> a >> b;
  p = Point(a, b);
  return is;
}

ostream &operator<<(ostream &os, Point &p) {
  return os << fixed << setprecision(10) << p.real() << " " << p.imag();
}

Point rotate(Real theta, const Point &p) {
  return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

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

struct Line {
  Point a, b;
  Line() = default;
  Line(Point a, Point b): a(a), b(b) {}

  friend ostream &operator<<(ostream &os, Line &p) {
    return os << p.a << " to " << p.b;
  }

  friend istream &operator>>(istream &is, Line &a) {
    return is >> a.a >> a.b;
  }
};

struct Circle {
  Point c;
  Real r;
  Circle() = default;
  Circle(Point c, Real r): c(c), r(r) {}

  friend ostream &operator<<(ostream &os, Circle &c) {
    return os << c.c << ": " << c.r;
  }

  friend istream &operator>>(istream &is, Circle &c) {
    return is >> c.c >> c.r;
  }
};

Real cross(const Point &a, const Point &b) {
  return real(a) * imag(b) - real(b) * imag(a);
}

Real dot(const Point &a, const Point &b) {
  return real(a) * real(b) + imag(a) * imag(b);
}

struct Segment : Line {
  Segment() = default;
  Segment(Point a, Point b) : Line(a, b) {}
};

int ccw(const Point &a, Point b, Point c) {
  b = b - a, c = c - a;
  if (cross(b, c) > EPS) return +1; // COUNTER_CLOCKWISE
  if (cross(b, c) < -EPS) return -1; // CLOCKWISE
  if (dot(b, c) < 0) return +2; // ONLINE_BACK
  if (norm(b) < norm(c)) return -2; // ONLINE_FRONT
  return 0; // ON_SEGMENT
}

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

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 Line &l, const Segment& s) {
  return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

int intersect(const Circle &c, const Circle &d) {
  Real dis = fabs(c.c - d.c);

  if (dis > c.r + d.r + EPS) return 4;
  else if (eq(dis, c.r + d.r)) return 3;
  else if (eq(dis, abs(c.r - d.r))) return 1;
  else if (dis + min(c.r, d.r) < max(c.r, d.r) - EPS) return 0;
  else return 2;
}

bool parallel(const Line &a, const Line &b) {
  return abs(cross(a.b - a.a, b.b - b.a)) < EPS;
}

bool orthogonal(const Line &a, const Line &b) {
  return abs(dot(a.b - a.a, b.b - b.a)) < EPS;
}

Point projection(const Line& s, const Point &p) {
  double t = dot(p - s.a, s.b - s.a) / norm(s.b - s. a);
  return s.a + (s.b - s.a) * t;
}

Point projection(const Segment& l, const Point &p) {
  return projection(Line(l), p);
}

Point reflection(const Line &l, const Point &p) {
  Point r = projection(l, p);
  return p + (r - p) * 2;
}

Real distance(const Line &l, const Point &p) {
  Point r = projection(l, p);
  return fabs(p - r);
}

Real distance(const Segment&s, const Point &p) {
  Point r = projection(s, p);
  if (intersect(s, r)) return abs(r - p);
  return min(abs(s.a - p), abs(s.b - p));
}

Real distance(const Segment& a, const Segment& b) {
  if (intersect(a, b)) return 0;
  return min({
               distance(a, b.a),
               distance(a, b.b),
               distance(b, a.a),
               distance(b, a.b)
             });
}

bool contains(const Circle &c, const Point &p) {
  if (fabs(c.c - p) < c.r + EPS) return true;
  return false;
}

Point crosspoint(const Line &l, const Line &m) {
  Real A = cross(l.b - l.a, m.b - m.a);
  Real B = cross(l.b - l.a, l.b - m.a);
  if (eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
  return m.a + (m.b - m.a) * B / A;
}

Point crosspoint(const Segment& l, const Segment& m) {
  return crosspoint(Line(l), Line(m));
}

Line bisector_of_angle(const Point& a, const Point& b, const Point& c) {
  Real d_ab = fabs(a - b);
  Real d_bc = fabs(b - c);
  Point c_ = b + (c - b) * d_ab / d_bc;

  return Line(b, (a + c_) * 0.5);
}

Line bisector(const Point& a, const Point& b) {
  Point c = (a + b) * 0.5;
  Point d = c + rotate(PI / 2, b - c);

  return Line(c, d);
}

int intersect(const Circle &c, const Line &l) {
  Real d = distance(l, c.c);

  if (d > c.r + EPS) return 0;
  if (eq(d, c.r)) return 1;
  return 2;
}

pair<Point, Point> crosspoint(const Circle& c, const Line& l) {
  Real d = distance(l, c.c);

  Point p = projection(l, c.c);
  if (intersect(c, l) == 1) return { p, p };

  Real d2 = sqrt(c.r * c.r - d * d);
  Point v = (l.a - l.b) * (1.0 / fabs(l.a - l.b));

  return { p + d2 * v, p - d2 * v };
}

vector<Point> crosspoint(const Circle &c, const Segment &s) {
  int isect = intersect(c, Line(s));
  if (isect == 0) return {};

  auto [p1, p2] = crosspoint(c, Line(s));

  vector<Point> res;
  if (ccw(s.a, s.b, p1) == 0) res.push_back(p1);
  if (ccw(s.a, s.b, p2) == 0) res.push_back(p2);

  if (res.size() == 2 && ccw(s.a, p1, p2) == 0) swap(res[0], res[1]);
  return res;
}

pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
  Real d = fabs(c1.c - c2.c);
  Real x1 = (c1.r * c1.r + d * d - c2.r * c2.r) / 2 / d;
  Real y = sqrt(c1.r * c1.r - x1 * x1);

  Point base = (c2.c * x1 + c1.c * (d - x1)) * (1.0 / d);
  Point v = rotate(PI / 2, c1.c - base);
  v = v / fabs(v);

  return { base + v * y, base - v * y };
}

pair<Point, Point> tangent(const Circle &c, const Point &p) {
  Real d = fabs(c.c - p);
  Real d2 = sqrt(d * d - c.r * c.r);
  Real a = acos(d2 / d);


  Point q = c.c - p;
  q = q / fabs(q);

//  cout << d << " " << d2 << " " << a << " " << q << endl;
  return {
    p + rotate(a, q) * d2,
    p + rotate(-a, q) * d2
  };
}

vector<Segment> common_tangent(Circle c1, Circle c2) {
  int isect = intersect(c1, c2);
  Real d = fabs(c1.c - c2.c);
  Point v = (c2.c - c1.c) / d;

  vector<Segment> res;

  if (isect == 0) {
    return {};
  } else if (isect == 1) {
    auto [p1, p2] = crosspoint(c1, Line(c1.c, c2.c));
    if (eq(fabs(p2 - c2.c), c2.r)) swap(p1, p2);

    Point v = p1 + rotate(PI/2, c2.c - p1);
    return { Segment(p1, v) };
  } else if (isect == 2) {
  } else if (isect == 3) {
    auto [p1, p2] = crosspoint(c1, c2);
    res.emplace_back(p1, rotate(PI / 2, c1.c - p1) + p1);
  } else {
    Real a = d * c1.r / (c1.r + c2.r);
    Point p = c1.c + v * a;

    Real d1 = sqrt(a * a - c1.r * c1.r), d2 = sqrt(norm(p - c2.c) - c2.r * c2.r);
    Real theta = acos(d1 / a);

//    cout << d << endl;
//    cout << a << " " << d1 << " " << d2 << " " << theta << ": " << p << endl;

    Point e = (c1.c - p) * (1.0 / fabs(c1.c - p));
    Point e1 = rotate(theta, e), e2 = rotate(-theta, e);

    res.emplace_back(p + e1 * d1, p - e1 * d2);
    res.emplace_back(p + e2 * d1, p - e2 * d2);
  }

  if (eq(c1.r, c2.r)) {
    Point e = rotate(PI / 2, v);
    res.push_back(Segment(c1.c + e * c1.r, c2.c + e * c1.r));
    res.push_back(Segment(c1.c - e * c1.r, c2.c - e * c1.r));
    return res;
  }

  if (c1.r > c2.r) swap(c1, c2);

  v = c1.c - c2.c;
  Point p = v * (1.0 / (c2.r - c1.r)) * c2.r + c2.c;

  auto [q1, q2] = tangent(c1, p);
  res.emplace_back(q1, crosspoint(c2, Line(p, q1)).first);
  res.emplace_back(q2, crosspoint(c2, Line(p, q2)).first);

  return res;
}

using Polygon = vector<Point>;

istream& operator>>(istream& is, Polygon &p) {
  for (int i = 0; i < p.size(); i++) is >> p[i];
  return is;
}

ostream& operator<<(ostream& os, Polygon &p) {
  for (int i = 0; i < p.size(); i++) os << p[i] << endl;
  return os;
}

Real area(const Polygon& p) {
  Real res = 0;
  for (int i = 0; i < p.size(); i++) {
    res += cross(p[i], p[(i + 1) % p.size()]);
  }
  return abs(res)/2;
}

Real arcarea(const Circle &c, const Point &p1_, const Point &p2_) {
  Point p1 = p1_ - c.c, p2 = p2_ - c.c;
  Real a2 = atan2(imag(p2), real(p2));
  Point p = rotate(-a2, p1);
  Real a1 = atan2(imag(p), real(p));
//  cout << p1 << " " << p2 << " --- " << a2 << " " << a1 << endl;
  return - a1 / 2 * c.r * c.r;
}

int contains(Polygon g,Point p){
  int n=g.size();
  bool x=false;
  for(int i=0;i<n;i++){
    Point a=g[i]-p,b=g[(i+1)%n]-p;
    if(fabs(cross(a,b)) < EPS and dot(a,b) < EPS) return 1;
    if(a.imag()>b.imag()) swap(a,b);
    if(a.imag() < EPS and EPS < b.imag() and cross(a,b) > EPS ) {
//      cout << a << " --- " << b << ": " << cross(a, b) << endl;
      x = !x;
    }
  }
  return (x?2:0);
}

Polygon convex_hull(Polygon Q) {
  sort(ALL(Q));

  Polygon upper({Q[0]}), lower({Q[0]});

  rep(i, 1, Q.size()) {
    while (upper.size() >= 2) {
      int _ccw = ccw(upper[upper.size() - 2], upper[upper.size() - 1], Q[i]);
      if (_ccw == 1) {
        upper.pop_back();
      } else {
        break;
      }
    }
    if (upper.size() <= 1) {
      upper.push_back(Q[i]);
    } else if (upper.size() > 1) {
      int _ccw = ccw(upper[upper.size() - 2], upper[upper.size() - 1], Q[i]);
      if (_ccw == -1 || _ccw == -2) {
        upper.push_back(Q[i]);
      }
    }
  }
  rep(i, 1, Q.size()) {
    while (lower.size() >= 2) {
      int _ccw = ccw(lower[lower.size() - 2], lower[lower.size() - 1], Q[i]);
      if (_ccw == -1) {
        lower.pop_back();
      } else {
        break;
      }
    }

    if (lower.size() <= 1) {
      lower.push_back(Q[i]);
    } else if (lower.size() > 1) {
      int _ccw = ccw(lower[lower.size() - 2], lower[lower.size() - 1], Q[i]);
      if (_ccw == 1 || _ccw == -2) {
        lower.push_back(Q[i]);
      }
    }
  }

  Polygon ret;

  rep(i, 0, lower.size()) {
    ret.push_back(lower[i]);
//    cout << lower[i] << endl;
  }

//  cout << " | " << endl;

  rrep(i, 0, upper.size()) {
    if (!eq(lower[0], upper[i]) && !eq(lower.back(), upper[i]))
      ret.push_back(upper[i]);
//    cout << upper[i] << endl;
  }

  int start = 0;

//  cout << ret.size() << endl;
  rep(i, 0, ret.size()) {
    if (ret[i].imag() < ret[start].imag() || (eq(ret[i].imag(), ret[start].imag()) && ret[i].real() < ret[start].real())) {
      start = i;
    }
  }

//  cout << ret.size() << endl;
//  rep(i, 0, ret.size()) {
//    auto p = ret[(i + start) % ret.size()];
//    cout << (int)p.real() << " " << (int)p.imag() << endl;
//  }
//
  return ret;
}

Real closest_pair(vector<Point> &pts, int l, int r) {
  int m = (l + r) / 2;
  if (r - l <= 1) {
    return INF;
  } else if (r - l == 2) {
    if (imag(pts[l]) > imag(pts[l + 1])) swap(pts[l], pts[l + 1]);
    return fabs(pts[l] - pts[l + 1]);
  }

  Real mid = pts[m].real();
  Real d = min(closest_pair(pts, l, m), closest_pair(pts, m, r));

  inplace_merge(pts.begin() + l, pts.begin() + m, pts.begin() + r, [](const Point &a, const Point& b) {
    return a.imag() < b.imag();
  });

  vector<Point> ret;

  for (int i = l; i < r; i++) {
    if (fabs(pts[i].real() - mid) >= d) continue;

    for (int j = ret.size() - 1; j >= 0; j--) {
      if (fabs(imag(ret[j]) - imag(pts[i])) >= d) break;
      chmin(d, fabs(ret[j] - pts[i]));
    }

    ret.emplace_back(pts[i]);
  }

  return d;
}

bool contains(const Polygon &a, const Polygon &b) {
  rep(i, 0, b.size()) {
    if (!contains(a, b[i])) return false;
  }
  return true;
}


Real distance(const Polygon &a, const Point &p) {
  if (contains(a, p)) return 0;
  Real res = INF;
  rep(i, 0, a.size()) {
    Segment as(a[i], a[(i + 1) % a.size()]);
    chmin(res, distance(as, p));
  }
  return res;
}

Real distance(const Polygon &a, const Polygon &b) {
//  if (contains(a, b) || contains(b, a)) return 0;
  Real res = INF;
  rep(i, 0, a.size()) chmin(res, distance(b, a[i]));
  rep(i, 0, b.size()) chmin(res, distance(a, b[i]));
  return res;
}

struct Point3d {
  Real x, y, z;
  Point3d() {}
  Point3d(Real x, Real y, Real z): x(x), y(y), z(z) {}
};

Real distance(const Point3d &a, const Point3d &b) {
  return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) + pow(a.z - b.z, 2));
}

void solve(int N, int M) {
  vector<pair<Point, int>> pts(N + M);
  rep(i, 0, N) {
    cin >> pts[i].fi;
    pts[i].se = 0;
  }
  rep(i, 0, M) {
    cin >> pts[i + N].fi;
    pts[i + N].se = 1;
  }
  if (N == 0 || M == 0 || (N == 1 && M == 1)) {
    cout << "YES" << endl;
    return;
  }

  bool on_line = true;
  rep(i, 2, N + M) {
    if (abs(ccw(pts[0].fi, pts[1].fi, pts[i].fi)) == 1) {
      on_line = false;
      break;
    }
  }

  if (on_line) {
    sort(ALL(pts));
    int sw = 0;
    rep(i, 0, N + M - 1) {
      if (pts[i].se != pts[i + 1].se) sw++;
    }
    if (sw == 1) {
      cout << "YES" << endl;
    } else {
      cout << "NO" << endl;
    }
    return;
  }


  rep(i, 0, N + M) {
    rep(j, i + 1, N + M) {
      if (pts[i].se != pts[j].se) continue;

      set<int> ccw_set[2];

      rep(k, 0, N + M) {
        ccw_set[pts[k].se].insert(ccw(pts[i].fi, pts[j].fi, pts[k].fi));
      }

      if (ccw_set[1 - pts[i].se].size() != 1) {
      } else if (ccw_set[pts[i].se].find(*ccw_set[1 - pts[i].se].begin()) != ccw_set[pts[i].se].end()) {
      } else {
        cout << "YES" << endl;
        return;
      }
    }
  }
  cout << "NO" << endl;
  return;
}

int main() {
  cin.tie();
  ios::sync_with_stdio(false);

  cout << fixed << setprecision(10);
  int N, M;
  while (cin >> N >> M && N + M) {
    solve(N, M);
  }
}
accuracy: 1
time_ms: 2110
memory_kb: 3540
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

constexpr double EPS = 1e-8;

inline int sgn(double x) { return x < -EPS ? -1 : x > EPS ? 1 : 0; }

inline int compare(double a, double b) { return sgn(a - b); }

struct Point {
    double x, y;

    Point() {}

    Point(double x, double y) : x(x), y(y) {}

    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }

    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }

    Point operator+(const Point& p) const { return Point(*this) += p; }

    Point operator-(const Point& p) const { return Point(*this) -= p; }

    double norm() const { return x * x + y * y; }

    friend ostream& operator<<(ostream& os, const Point& p) { return os << p.x << ' ' << p.y; }
};

double dot(Point p, Point q) { return p.x * q.x + p.y * q.y; }

double cross(Point p, Point q) { return p.x * q.y - p.y * q.x; }

enum Position { COUNTER_CLOCKWISE = +1, CLOCKWISE = -1, ONLINE_BACK = +2, ONLINE_FRONT = -2, ON_SEGMENT = 0 };

Position ccw(Point a, Point b, Point c) {
    b -= a, c -= a;
    if (sgn(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sgn(cross(b, c)) == -1) return CLOCKWISE;
    if (sgn(dot(b, c)) == -1) return ONLINE_BACK;
    if (compare(b.norm(), c.norm()) == -1) return ONLINE_FRONT;
    return ON_SEGMENT;
}

void solve(int n, int m) {
    vector<vector<Point>> ps(2);
    vector<Point> cand;
    for (int i = 0; i < n; i++) {
        int x, y;
        cin >> x >> y;
        ps[0].emplace_back(x, y);
        cand.emplace_back(x, y);
    }
    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;
        ps[1].emplace_back(x, y);
        cand.emplace_back(x, y);
    }

    auto check = [&](Point p, Point q) {
        int a = 0, b = 0;
        vector<pair<double, int>> line;
        for (int i = 0; i < 2; i++) {
            for (auto& r : ps[i]) {
                int val = ccw(p, q, r);
                if (abs(val) == 1) {
                    if (i == 0) {
                        if (a == 0)
                            a = val;
                        else if (val != a)
                            return false;
                    } else {
                        if (b == 0)
                            b = val;
                        else if (val != b)
                            return false;
                    }
                } else
                    line.emplace_back(sgn((p - q).x) != 0 ? (r - q).x / (p - q).x : (r - q).y / (p - q).y, i);
            }
        }
        if (a != 0 and b != 0 and a == b) return false;
        sort(line.begin(), line.end());
        for (size_t i = 0, cnt = 0; i + 1 < line.size(); i++) {
            if (line[i].second == line[i + 1].second) continue;
            if (++cnt == 2) return false;
        }
        return true;
    };
    for (int i = 0; i < n + m; i++) {
        for (int j = i + 1; j < n + m; j++) {
            if (check(cand[i], cand[j])) {
                cout << "YES" << '\n';
                return;
            }
        }
    }

    cout << "NO" << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    for (int n, m; cin >> n >> m, n;) solve(n, m);
}
accuracy: 1
time_ms: 130
memory_kb: 3280
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < int(n); i++)
#define per(i, n) for (int i = (n)-1; 0 <= i; i--)
#define rep2(i, l, r) for (int i = (l); i < int(r); i++)
#define per2(i, l, r) for (int i = (r)-1; int(l) <= i; i--)
#define MM << " " <<
#define pb push_back
#define eb emplace_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define sz(x) (int)x.size()

template<typename T>
void print(const vector<T> &v, T x = 0) {
    int n = v.size();
    for (int i = 0; i < n; i++) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (v.empty()) cout << '\n';
}

template<class T>
using MaxHeap = priority_queue<T>;
template<class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

using ll  = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template<typename T>
bool chmax(T &x, const T &y) {
    return (x < y) ? (x = y, true) : false;
}

template<typename T>
bool chmin(T &x, const T &y) {
    return (x > y) ? (x = y, true) : false;
}

using P = pair<ll, ll>;

ll dot(P x, P y) {
    return x.first * y.first + x.second * y.second;
}
ll det(P x, P y) {
    return x.first * y.second - x.second * y.first;
}

P diff(const P &b, const P &a) {
    return {b.first - a.first, b.second - a.second};
}

int ccw(const P &a, P b, P c) {
    b = diff(b, a);
    c = diff(c, a);
    if(det(b, c) > 0) return  +1;
    if(det(b, c) < 0) return  -1;
    if(dot(b, c) < 0) return +2;
    if(c.first * c.first + c.second * c.second - b.second * b.second - c.first * c.first > 0) return  -2;
    return 0;
}

bool intersect(pair<P, P> &s, pair<P, P> &t) {
    if(ccw(s.first, s.second, t.first) * ccw(s.first, s.second, t.second) > 0) return false;
    return ccw(t.first, t.second, t.first) * ccw(t.first, t.second, s.second) <= 0;
}

vector<P> convexHull(vector<P> p) {
    sort(all(p));
    p.erase(unique(all(p)), end(p));
    int n = p.size(), k = 0;
    if(n == 1) return p;
    vector<P> ch(2 * n);
    for(int i = 0; i < n; ch[k++] = p[i++]) {
        while(k >= 2 && det(diff(ch[k-1], ch[k-2]), diff(p[i], ch[k-1])) <= 0) {
            --k;
        }
    }
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
        while(k >= t && det(diff(ch[k-1], ch[k-2]), diff(p[i], ch[k-1])) <= 0) {
            --k;
        }
    }
    ch.resize(k - 1);
    return ch;
}

bool in_poly(const vector<P> &p, P &q) {
    if(p.size() == 1) return false; 
    int n = p.size();
    int ret = 0;
    rep(i,n) {
        auto a = diff(p[i], q), b = diff(p[(i + 1) % n], q);
        if(det(a, b) == 0 && dot(a, b) <= 0) return 1;
        if(a.second > b.second) swap(a, b);
        if(a.second <= 0 && b.second > 0 && det(a, b) > 0) ret ^= 2;
    }
    return ret;
}

bool onSeg(P a, P b, P c) {
    a = diff(a, c);
    b = diff(b, c);
    if(det(a, b)) return false;
    if(a.first > b.first) swap(a, b);
    return a.first <= c.first && c.first <= b.first;
}

bool solve(int n, int m) {
    vector<P> black(n), white(m);
    for(auto &i: black) cin >> i.first >> i.second;
    for(auto &i: white) cin >> i.first >> i.second;
    black = convexHull(black);
    white = convexHull(white);
    // for(auto &i : black) cout << "(" MM i.first MM i.second MM ")" << endl;
    // for(auto &i : white) cout << "(" MM i.first MM i.second MM ")" << endl;

    if(black.size() > white.size()) swap(black, white);

    if(black.size() == 1) {
        if(white.size() == 1) return true;
        else if(white.size() == 2) return ccw(white[0], white[1], black[0]) != 0;
        else return !in_poly(white, black[0]);
    } else if(black.size() == 2) {
        pair<P, P> c = {black[0], black[1]};
        int pp = white.size();
        rep(i,pp) {
            pair<P, P> d = {white[i], white[(i + 1) % pp]};
            if(intersect(c, d)) return false;
        }
        return true;
    } else {
        bool res = true;
        for(auto &i : black) {
            res = res & !in_poly(white, i);
        }
        for(auto &i : white) {
            res = res & !in_poly(black, i);
        }
        return res;
    }
}

int main() {
    int n, m;
    vector<bool> ans;
    while(1) {
        cin >> n >> m;
        if(n == 0 && m == 0) break;
        ans.eb(solve(n, m));
    }
    for(auto &&i : ans) cout << (i ? "YES" : "NO") << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3356
final_rank: 3

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

namespace geometry {
    // Point : 複素数型を位置ベクトルとして扱う
    // 実軸(real)をx軸、挙軸(imag)をy軸として見る
    using D = long double;
    using Point = complex<D>;
    const D EPS = 1e-7;
    const D PI = acosl(-1);

    inline bool equal(const D &a, const D &b) { return fabs(a - b) < EPS; }

    // 単位ベクトル(unit vector)を求める
    Point unitVector(const Point &a) { return a / abs(a); }

    // 法線ベクトル(normal vector)を求める
    // 90度回転した単位ベクトルをかける
    // -90度がよければPoint(0, -1)をかける
    Point normalVector(const Point &a) { return a * Point(0, 1); }

    // 内積(dot product) : a・b = |a||b|cosΘ
    D dot(const Point &a, const Point &b) {
        return (a.real() * b.real() + a.imag() * b.imag());
    }

    // 外積(cross product) : a×b = |a||b|sinΘ
    D cross(const Point &a, const Point &b) {
        return (a.real() * b.imag() - a.imag() * b.real());
    }

    // 点pを反時計回りにtheta度回転
    // thetaはラジアン！！！
    Point rotate(const Point &p, const D &theta) {
        return Point(cos(theta) * p.real() - sin(theta) * p.imag(),
                     sin(theta) * p.real() + cos(theta) * p.imag());
    }

    // ラジアン->度
    D radianToDegree(const D &radian) { return radian * 180.0 / PI; }

    // 度->ラジアン
    D degreeToRadian(const D &degree) { return degree * PI / 180.0; }

    // 点の回転方向
    // 点a, b, cの位置関係について(aが基準点)
    int ccw(const Point &a, Point b, Point c) {
        b -= a, c -= a;
        // 点a, b, c が
        // 反時計回りの時、
        if(cross(b, c) > EPS) return 1;
        // 時計回りの時、
        if(cross(b, c) < -EPS) return -1;
        // c, a, bがこの順番で同一直線上にある時、
        if(dot(b, c) < 0) return 2;
        // a, b, cがこの順番で同一直線上にある場合、
        if(norm(b) < norm(c)) return -2;
        // cが線分ab上にある場合、
        return 0;
    }

    // Line : 直線を表す構造体
    // b - a で直線・線分を表せる
    struct Line {
        Point a, b;
        Line() = default;
        Line(Point a, Point b) : a(a), b(b) {}
        // Ax+By=C
        Line(D A, D B, D C) {
            if(equal(A, 0)) {
                a = Point(0, C / B), b = Point(1, C / B);
            } else if(equal(B, 0)) {
                b = Point(C / A, 0), b = Point(C / A, 1);
            } else {
                a = Point(0, C / B), b = Point(C / A, 0);
            }
        }
    };

    // Segment : 線分を表す構造体
    // Lineと同じ
    struct Segment : Line {
        Segment() = default;

        Segment(Point a, Point b) : Line(a, b) {}
    };

    // Circle : 円を表す構造体
    // pが中心の位置ベクトル、rは半径
    struct Circle {
        Point p;
        D r;

        Circle() = default;

        Circle(Point p, D r) : p(p), r(r) {}
    };

    // 2直線の直交判定 : a⊥b <=> dot(a, b) = 0
    bool isOrthogonal(const Line &a, const Line &b) {
        return equal(dot(a.b - a.a, b.b - b.a), 0);
    }
    // 2直線の平行判定 : a//b <=> cross(a, b) = 0
    bool isParallel(const Line &a, const Line &b) {
        return equal(cross(a.b - a.a, b.b - b.a), 0);
    }

    // 点cが直線ab上にあるか
    bool isPointOnLine(const Point &a, const Point &b, const Point &c) {
        return isParallel(Line(a, b), Line(a, c));
    }

    // 点cが"線分"ab上にあるか
    bool isPointOnSegment(const Point &a, const Point &b, const Point &c) {
        // |a-c| + |c-b| <= |a-b| なら線分上
        return (abs(a - c) + abs(c - b) < abs(a - b) + EPS);
    }

    // 直線lと点pの距離を求める
    D distanceBetweenLineAndPoint(const Line &l, const Point &p) {
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }

    // 線分lと点pの距離を求める
    // 定義：点pから「線分lのどこか」への最短距離
    D distanceBetweenSegmentAndPoint(const Segment &l, const Point &p) {
        if(dot(l.b - l.a, p - l.a) < EPS) return abs(p - l.a);
        if(dot(l.a - l.b, p - l.b) < EPS) return abs(p - l.b);
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }

    // 直線s, tの交点の計算
    Point crossPoint(const Line &s, const Line &t) {
        D d1 = cross(s.b - s.a, t.b - t.a);
        D d2 = cross(s.b - s.a, s.b - t.a);
        if(equal(abs(d1), 0) && equal(abs(d2), 0)) return t.a;
        return t.a + (t.b - t.a) * (d2 / d1);
    }

    // 線分s, tの交点の計算
    Point crossPoint(const Segment &s, const Segment &t) {
        return crossPoint(Line(s), Line(t));
    }

    // 線分sと線分tが交差しているかどうか
    // bound:線分の端点を含むか
    bool isIntersect(const Segment &s, const Segment &t, bool bound) {
        return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) < bound &&
               ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) < bound;
    }

    // 線分sとtの距離
    D distanceBetweenSegments(const Segment &s, const Segment &t) {
        if(isIntersect(s, t, 1)) return (D)(0);
        D ans = distanceBetweenSegmentAndPoint(s, t.a);
        chmin(ans, distanceBetweenSegmentAndPoint(s, t.b));
        chmin(ans, distanceBetweenSegmentAndPoint(t, s.a));
        chmin(ans, distanceBetweenSegmentAndPoint(t, s.b));
        return ans;
    }

    // 射影(projection)
    // 直線(線分)lに点pから引いた垂線の足を求める
    Point projection(const Line &l, const Point &p) {
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    Point projection(const Segment &l, const Point &p) {
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    // 反射(reflection)
    // 直線lを対称軸として点pと線対称の位置にある点を求める
    Point reflection(const Line &l, const Point &p) {
        return p + (projection(l, p) - p) * (D)2.0;
    }

    // 2つの円の交差判定
    // 返り値は共通接線の数
    int isIntersect(const Circle &c1, const Circle &c2) {
        D d = abs(c1.p - c2.p);
        // 2つの円が離れている場合
        if(d > c1.r + c2.r + EPS) return 4;
        // 外接している場合
        if(equal(d, c1.r + c2.r)) return 3;
        // 内接している場合
        if(equal(d, abs(c1.r - c2.r))) return 1;
        // 内包している場合
        if(d < abs(c1.r - c2.r) - EPS) return 0;
        return 2;
    }

    // 2つの円の交点
    vector<Point> crossPoint(const Circle &c1, const Circle &c2) {
        vector<Point> res;
        int mode = isIntersect(c1, c2);
        // 2つの中心の距離
        D d = abs(c1.p - c2.p);
        // 2円が離れている場合
        if(mode == 4) return res;
        // 1つの円がもう1つの円に内包されている場合
        if(mode == 0) return res;
        // 2円が外接する場合
        if(mode == 3) {
            D t = c1.r / (c1.r + c2.r);
            res.emplace_back(c1.p + (c2.p - c1.p) * t);
            return res;
        }
        // 内接している場合
        if(mode == 1) {
            if(c2.r < c1.r - EPS) {
                res.emplace_back(c1.p + (c2.p - c1.p) * (c1.r / d));
            } else {
                res.emplace_back(c2.p + (c1.p - c2.p) * (c2.r / d));
            }
            return res;
        }
        // 2円が重なる場合
        D rc1 = (c1.r * c1.r + d * d - c2.r * c2.r) / (2 * d);
        D rs1 = sqrt(c1.r * c1.r - rc1 * rc1);
        if(c1.r - abs(rc1) < EPS) rs1 = 0;
        Point e12 = (c2.p - c1.p) / abs(c2.p - c1.p);
        res.emplace_back(c1.p + rc1 * e12 + rs1 * e12 * Point(0, 1));
        res.emplace_back(c1.p + rc1 * e12 + rs1 * e12 * Point(0, -1));
        return res;
    }

    // 点pが円cの内部(円周上も含む)に入っているかどうか
    bool isInCircle(const Circle &c, const Point &p) {
        D d = abs(c.p - p);
        return (equal(d, c.r) || d < c.r - EPS);
    }

    // 円cと直線lの交点
    vector<Point> crossPoint(const Circle &c, const Line &l) {
        vector<Point> res;
        D d = distanceBetweenLineAndPoint(l, c.p);
        // 交点を持たない
        if(d > c.r + EPS) return res;
        // 接する
        Point h = projection(l, c.p);
        if(equal(d, c.r)) {
            res.emplace_back(h);
            return res;
        }
        Point e = unitVector(l.b - l.a);
        D ph = sqrt(c.r * c.r - d * d);
        res.emplace_back(h - e * ph);
        res.emplace_back(h + e * ph);
        return res;
    }

    // 点pを通る円cの接線
    // 2本あるので、接点のみを返す
    vector<Point> tangentToCircle(const Point &p, const Circle &c) {
        return crossPoint(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
    }

    // 円の共通接線
    vector<Line> tangent(const Circle &a, const Circle &b) {
        vector<Line> ret;
        // 2円の中心間の距離
        D g = abs(a.p - b.p);
        // 円が内包されている場合
        if(equal(g, 0)) return ret;
        Point u = unitVector(b.p - a.p);
        Point v = rotate(u, PI / 2);
        for(int s : {-1, 1}) {
            D h = (a.r + b.r * s) / g;
            if(equal(h * h, 1)) {
                ret.emplace_back(a.p + (h > 0 ? u : -u) * a.r,
                                 a.p + (h > 0 ? u : -u) * a.r + v);

            } else if(1 - h * h > 0) {
                Point U = u * h, V = v * sqrt(1 - h * h);
                ret.emplace_back(a.p + (U + V) * a.r,
                                 b.p - (U + V) * (b.r * s));
                ret.emplace_back(a.p + (U - V) * a.r,
                                 b.p - (U - V) * (b.r * s));
            }
        }
        return ret;
    }

    // 多角形の面積を求める
    D PolygonArea(const vector<Point> &p) {
        D res = 0;
        int n = p.size();
        for(int i = 0; i < n - 1; i++) res += cross(p[i], p[i + 1]);
        res += cross(p[n - 1], p[0]);
        return res * 0.5;
    }

    // 凸多角形かどうか
    bool isConvex(const vector<Point> &p) {
        int n = p.size();
        int now, pre, nxt;
        for(int i = 0; i < n; i++) {
            pre = (i - 1 + n) % n;
            nxt = (i + 1) % n;
            now = i;
            if(ccw(p[pre], p[now], p[nxt]) == -1) return false;
        }
        return true;
    }

    // 凸包 O(NlogN)
    vector<Point> ConvexHull(vector<Point> &p) {
        int n = (int)p.size(), k = 0;
        sort(all(p), [](const Point &a, const Point &b) {
            return (real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b));
        });
        vector<Point> ch(2 * n);
        // 一直線上の3点を含める -> (< -EPS)
        // 含め無い -> (< EPS)
        for(int i = 0; i < n; ch[k++] = p[i++]) { // lower
            while(k >= 2 &&
                  cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < EPS)
                --k;
        }
        for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) { // upper
            while(k >= t &&
                  cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < EPS)
                --k;
        }
        ch.resize(k - 1);
        return ch;
    }

    // 多角形gに点pが含まれているか?
    // 含まれる:2, 辺上にある:1, 含まれない:0
    int isContained(const vector<Point> &g, const Point &p) {
        bool in = false;
        int n = (int)g.size();
        for(int i = 0; i < n; i++) {
            Point a = g[i] - p, b = g[(i + 1) % n] - p;
            if(imag(a) > imag(b)) swap(a, b);
            if(imag(a) <= EPS && EPS < imag(b) && cross(a, b) < -EPS) in = !in;
            if(cross(a, b) == 0 && dot(a, b) <= 0) return 1;
        }
        return (in ? 2 : 0);
    }

    vector<Point> convex_cut(const vector<Point> &g, Line l){
        vector<Point> ret;
        for(int i=0; i<g.size(); i++){
            Point now = g[i], nxt = g[(i+1)%g.size()];
            if(ccw(l.a,l.b,now) != -1) ret.push_back(now);
            if(ccw(l.a,l.b,now) * ccw(l.a,l.b,nxt) < 0){
                ret.push_back(crossPoint(Line(now,nxt),l));
            }
        }
        return ret;
    }

    bool equal (const Point &a, const Point &b) {
        return equal(a.real(),b.real()) && equal(a.imag(),b.imag());
    }

    D circlesIntersectArea(Circle &a, Circle &b){
        double d = abs(a.p - b.p);
        if(d >= a.r + b.r - EPS) return 0; //2円が離れている
        auto R = minmax(a.r,b.r);
        if(d <= R.second - R.first + EPS) return R.first*R.first*pi; //円が円を内包する
        D theta1 = acos((d*d + a.r*a.r - b.r*b.r)/(2*a.r*d));
        D theta2 = acos((d*d + b.r*b.r - a.r*a.r)/(2*b.r*d));
        D ret = a.r*a.r*(theta1-cos(theta1)*sin(theta1)) + b.r*b.r*(theta2-cos(theta2)*sin(theta2));
        return ret;
    }
} // namespace geometry

using namespace geometry;

bool solve(){
    int n,m; cin >> n >> m;
    if(!n) return false;
    int N = n+m;
    vector<Point> a(n),b(m),c(N);
    rep(i,n){
        int x,y; cin >> x >> y;
        a[i] = Point(x,y);
        c[i] = Point(x,y);
    }
    rep(i,m){
        int x,y; cin >> x >> y;
        b[i] = Point(x,y);
        c[i+n] = Point(x,y);
    }
    auto comp = [&](pair<Point,int> a, pair<Point,int> b) -> bool {
        if(a.first.real() != b.first.real()) return a.first.real() < b.first.real();
        if(a.first.imag() != b.first.imag()) return a.first.imag() < b.first.imag();
        return a.second < b.second;
    };
    rep(i,N) rep(j,i){
        vector<pair<Point,int>> zeros;
        rep(l,2){
            bool f = true;
            rep(k,n){
                int cres = ccw(a[k],c[i],c[j]);
                if(abs(cres) == 1){
                    cres = (cres + 1) / 2;
                    if(l != cres) f = false;
                }else{
                    zeros.emplace_back(a[k],0);
                }
            }
            rep(k,m){
                int cres = ccw(b[k],c[i],c[j]);
                if(abs(cres) == 1){
                    cres = (cres + 1) / 2;
                    if(1-l != cres) f = false;
                }else{
                    zeros.emplace_back(b[k],1);
                }
            }
            if(!f) continue;
            sort(all(zeros),comp);
            int diff = 0;
            int sz = zeros.size();
            rep(k,sz-1){
                if(zeros[k].second != zeros[k+1].second) diff++;
            }
            if(diff <= 1){
                cout << "YES\n";
                return true;
            }
        }
    }
    cout << "NO\n";
    return true;
}

int main(){
    while(solve());
}
accuracy: 1
time_ms: 4020
memory_kb: 3104
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

using T = double;
using Vec = std::complex<T>;

const T PI = std::acos(-1);

constexpr T eps = 1e-12;
inline bool eq(T a, T b) { return std::abs(a - b) < eps; }
inline bool eq(Vec a, Vec b) { return std::abs(a - b) < eps; }
inline bool lt(T a, T b) { return a < b - eps; }
inline bool leq(T a, T b) { return a < b + eps; }

std::istream& operator>>(std::istream& is, Vec& p) {
    T x, y;
    is >> x >> y;
    p = {x, y};
    return is;
}

struct Line {
    Vec p1, p2;
    Line() = default;
    Line(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Segment {
    Vec p1, p2;
    Segment() = default;
    Segment(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Circle {
    Vec c;
    T r;
    Circle() = default;
    Circle(const Vec& c, T r) : c(c), r(r) {}
};

using Polygon = std::vector<Vec>;

T dot(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).real();
}

T cross(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).imag();
}

Vec rot(const Vec& a, T ang) {
    return a * Vec(std::cos(ang), std::sin(ang));
}

Vec projection(const Line& l, const Vec& p) {
    return l.p1 + dot(p - l.p1, l.dir()) * l.dir() / std::norm(l.dir());
}

Vec reflection(const Line& l, const Vec& p) {
    return T(2) * projection(l, p) - p;
}

// 0: collinear
// 1: counter-clockwise
// 2: clockwise
int ccw(const Vec& a, const Vec& b, const Vec& c) {
    if (eq(cross(b - a, c - a), 0)) return 0;
    if (lt(cross(b - a, c - a), 0)) return -1;
    return 1;
}

Line bisector(const Vec& p, const Vec& q) {
    auto m = (p + q) / T(2);
    auto v = q - p;
    return Line(m, m + Vec(-v.imag(), v.real()));
}

bool intersect(const Segment& s, const Vec& p) {
    Vec u = s.p1 - p, v = s.p2 - p;
    return eq(cross(u, v), 0) && leq(dot(u, v), 0);
}

// 0: outside
// 1: on the border
// 2: inside
int intersect(const Polygon& poly, const Vec& p) {
    const int n = poly.size();
    bool in = 0;
    for (int i = 0; i < n; ++i) {
        auto a = poly[i] - p, b = poly[(i+1)%n] - p;
        if (eq(cross(a, b), 0) && (lt(dot(a, b), 0) || eq(dot(a, b), 0))) return 1;
        if (a.imag() > b.imag()) std::swap(a, b);
        if (leq(a.imag(), 0) && lt(0, b.imag()) && lt(cross(a, b), 0)) in ^= 1;
    }
    return in ? 2 : 0;
}

bool intersect(const Segment& s, const Segment& t) {
    auto a = s.p1, b = s.p2;
    auto c = t.p1, d = t.p2;
    if (ccw(a, b, c) != ccw(a, b, d) && ccw(c, d, a) != ccw(c, d, b)) return 2;
    if (intersect(s, c) || intersect(s, d) || intersect(t, a) || intersect(t, b)) return 1;
    return 0;
}

bool intersect(const Polygon& poly1, const Polygon& poly2) {
    const int n = poly1.size();
    const int m = poly2.size();
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (intersect(Segment(poly1[i], poly1[(i+1)%n]), Segment(poly2[j], poly2[(j+1)%n]))) {
                return true;
            }
        }
    }
    return intersect(poly1, poly2[0]) || intersect(poly2, poly1[0]);
}


// 0: inside
// 1: inscribe
// 2: intersect
// 3: circumscribe
// 4: outside
int intersect(const Circle& c1, const Circle& c2) {
    T d = std::abs(c1.c - c2.c);
    if (lt(d, std::abs(c2.r - c1.r))) return 0;
    if (eq(d, std::abs(c2.r - c1.r))) return 1;
    if (eq(c1.r + c2.r, d)) return 3;
    if (lt(c1.r + c2.r, d)) return 4;
    return 2;
}

T dist(const Line& l, const Vec& p) {
    return std::abs(cross(p - l.p1, l.dir())) / std::abs(l.dir());
}

T dist(const Segment& s, const Vec& p) {
    if (lt(dot(p - s.p1, s.dir()), 0)) return std::abs(p - s.p1);
    if (lt(dot(p - s.p2, -s.dir()), 0)) return std::abs(p - s.p2);
    return std::abs(cross(p - s.p1, s.dir())) / std::abs(s.dir());
}

T dist(const Segment& s, const Segment& t) {
    if (intersect(s, t)) return T(0);
    return std::min({dist(s, t.p1), dist(s, t.p2), dist(t, s.p1), dist(t, s.p2)});
}

Vec intersection(const Line& l, const Line& m) {
    Vec r = m.p1 - l.p1;
    assert(!eq(cross(l.dir(), m.dir()), 0)); // not parallel
    return l.p1 + cross(m.dir(), r) / cross(m.dir(), l.dir()) * l.dir();
}

std::vector<Vec> intersection(const Circle& c, const Line& l) {
    T d = dist(l, c.c);
    if (lt(c.r, d)) return {};  // no intersection
    Vec e1 = l.dir() / std::abs(l.dir());
    Vec e2 = Vec(-e1.imag(), e1.real());
    if (ccw(c.c, l.p1, l.p2) == 1) e2 *= -1;
    if (eq(c.r, d)) return {c.c + d*e2};  // tangent
    T t = std::sqrt(c.r*c.r - d*d);
    return {c.c + d*e2 + t*e1, c.c + d*e2 - t*e1};
}

std::vector<Vec> intersection(const Circle& c1, const Circle& c2) {
    T d = std::abs(c1.c - c2.c);
    if (lt(c1.r + c2.r, d)) return {};  // outside
    Vec e1 = (c2.c - c1.c) / std::abs(c2.c - c1.c);
    Vec e2 = Vec(-e1.imag(), e1.real());
    if (lt(d, std::abs(c2.r - c1.r))) return {};  // contain
    if (eq(d, std::abs(c2.r - c1.r))) return {c1.c + c1.r*e1};  // tangent
    T x = (c1.r*c1.r - c2.r*c2.r + d*d) / (2*d);
    T y = std::sqrt(c1.r*c1.r - x*x);
    return {c1.c + x*e1 + y*e2, c1.c + x*e1 - y*e2};
}

T area(const Polygon& poly) {
    const int n = poly.size();
    T res = 0;
    for (int i = 0; i < n; ++i) {
        res += cross(poly[i], poly[(i + 1) % n]);
    }
    return std::abs(res) / T(2);
}

T area_intersection(const Circle& c1, const Circle& c2) {
    T d = std::abs(c2.c - c1.c);
    if (leq(c1.r + c2.r, d)) return 0;  // outside
    if (leq(d, std::abs(c2.r - c1.r))) {  // inside
        T r = std::min(c1.r, c2.r);
        return PI * r * r;
    }
    T ans = 0;
    T a;
    a = std::acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    ans += c1.r*c1.r*(a - std::sin(a)*std::cos(a));
    a = std::acos((c2.r*c2.r+d*d-c1.r*c1.r)/(2*c2.r*d));
    ans += c2.r*c2.r*(a - std::sin(a)*std::cos(a));
    return ans;
}

bool is_convex(const Polygon& poly) {
    int n = poly.size();
    for (int i = 0; i < n; ++i) {
        if (lt(cross(poly[(i+1)%n] - poly[i], poly[(i+2)%n] - poly[(i+1)%n]), 0)) {
            return false;
        }
    }
    return true;
}

std::vector<Vec> convex_cut(const Polygon& poly, const Line& l) {
    const int n = poly.size();
    std::vector<Vec> res;
    for (int i = 0; i < n; ++i) {
        auto p = poly[i], q = poly[(i+1)%n];
        if (ccw(l.p1, l.p2, p) != -1) {
            if (res.empty() || !eq(res.back(), p)) {
                res.push_back(p);
            }
        }
        if (ccw(l.p1, l.p2, p) * ccw(l.p1, l.p2, q) < 0) {
            auto c = intersection(Line(p, q), l);
            if (res.empty() || !eq(res.back(), c)) {
                res.push_back(c);
            }
        }
    }
    return res;
}

Vec centroid(const Vec& A, const Vec& B, const Vec& C) {
    assert(ccw(A, B, C) != 0);
    return (A + B + C) / T(3);
}

Vec incenter(const Vec& A, const Vec& B, const Vec& C) {
    assert(ccw(A, B, C) != 0);
    T a = std::abs(B - C);
    T b = std::abs(C - A);
    T c = std::abs(A - B);
    return (a*A + b*B + c*C) / (a + b + c);
}

Vec circumcenter(const Vec& A, const Vec& B, const Vec& C) {
    assert(ccw(A, B, C) != 0);
    return intersection(bisector(A, B), bisector(A, C));
}

// large error but beautiful
// Vec circumcenter(const Vec& A, const Vec& B, const Vec& C) {
//     assert(ccw(A, B, C) != 0);
//     Vec p = C - B, q = A - C, r = B - A;
//     T a = std::norm(p) * dot(q, r);
//     T b = std::norm(q) * dot(r, p);
//     T c = std::norm(r) * dot(p, q);
//     return (a*A + b*B + c*C) / (a + b + c);
// }

std::pair<Vec, Vec> tangent_points(const Circle& c, const Vec& p) {
    auto m = (p + c.c) / T(2);
    auto is = intersection(c, Circle(m, std::abs(p - m)));
    return {is[0], is[1]};
}

// for each l, l.p1 is a tangent point of c1
std::vector<Line> common_tangents(Circle c1, Circle c2) {
    assert(!eq(c1.c, c2.c) || !eq(c1.r, c2.r));
    int cnt = intersect(c1, c2);  // number of common tangents
    std::vector<Line> ret;
    if (cnt == 0) {
        return ret;
    }

    // external
    if (eq(c1.r, c2.r)) {
        auto d = c2.c - c1.c;
        Vec e(-d.imag(), d.real());
        e = e / std::abs(e) * c1.r;
        ret.push_back(Line(c1.c + e, c1.c + e + d));
        ret.push_back(Line(c1.c - e, c1.c - e + d));
    } else {
        auto p = (-c2.r*c1.c + c1.r*c2.c) / (c1.r - c2.r);
        if (cnt == 1) {
            Vec q(-p.imag(), p.real());
            return {Line(p, q)};
        } else {
            auto [a, b] = tangent_points(c1, p);
            ret.push_back(Line(a, p));
            ret.push_back(Line(b, p));
        }
    }

    // internal
    auto p = (c2.r*c1.c + c1.r*c2.c) / (c1.r + c2.r);
    if (cnt == 3) {
        Vec q(-p.imag(), p.real());
        ret.push_back(Line(p, q));
    } else if (cnt == 4) {
        auto [a, b] = tangent_points(c1, p);
        ret.push_back(Line(a, p));
        ret.push_back(Line(b, p));
    }

    return ret;
}

void sort_by_arg(std::vector<Vec>& pts) {
    std::sort(pts.begin(), pts.end(), [&](auto& p, auto& q) {
        if ((p.imag() < 0) != (q.imag() < 0)) return (p.imag() < 0);
        if (cross(p, q) == 0) {
            if (p == Vec(0, 0)) return !(q.imag() < 0 || (q.imag() == 0 && q.real() > 0));
            if (q == Vec(0, 0)) return  (p.imag() < 0 || (p.imag() == 0 && p.real() > 0));
            return (p.real() > q.real());
        }
        return (cross(p, q) > 0);
    });
}

std::vector<Vec> convex_hull(std::vector<Vec>& pts) {
    int n = pts.size();
    if (n == 1) return pts;
    std::sort(pts.begin(), pts.end(), [](const Vec& v1, const Vec& v2) {
        return (v1.imag() != v2.imag()) ? (v1.imag() < v2.imag()) : (v1.real() < v2.real());
    });
    int k = 0; // the number of vertices in the convex hull
    std::vector<Vec> ch(2 * n);
    // right
    for (int i = 0; i < n; ++i) {
        while (k > 1 && lt(cross(ch[k-1] - ch[k-2], pts[i] - ch[k-1]), 0)) --k;
        ch[k++] = pts[i];
    }
    int t = k;
    // left
    for (int i = n - 2; i >= 0; --i) {
        while (k > t && lt(cross(ch[k-1] - ch[k-2], pts[i] - ch[k-1]), 0)) --k;
        ch[k++] = pts[i];
    }
    ch.resize(k - 1);
    return ch;
}

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) os << v[i] << " ";
    return os;
}


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int n, m;
        cin >> n >> m;
        if (n == 0 && m == 0) break;
        vector<Vec> black(n), white(m);
        for (auto& p : black) cin >> p;
        for (auto& p : white) cin >> p;
        black = convex_hull(black);
        white = convex_hull(white);
        cout << (intersect(black, white) ? "NO" : "YES") << "\n";
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3456
final_rank: 10

code_snippet: #line 2 "library/bits/stdc++.h"

// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
#line 2 "Source.cpp"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#line 2 "library/kotamanegi/geometry.hpp"
#define _USE_MATH_DEFINES
using namespace std;

typedef long double ld;
typedef complex<ld> Point;
typedef pair<Point, Point> Segment;
typedef Segment Line;
typedef vector<Point> Polygon;

const ld EPS = 1e-10;

ld abs(Line x)
{
  return abs(x.second - x.first);
}

// dot = |a||b| cos(theta)
ld dot(Point a, Point b)
{
  return a.real() * b.real() + a.imag() * b.imag();
}

// cross = |a||b| sin(theta)
ld cross(Point a, Point b)
{
  return a.real() * b.imag() - a.imag() * b.real();
}

// 射影: 直線sと点pから引いた垂線の交点
Point projection(Line s, Point p)
{
  Point base = s.second - s.first;
  ld r = dot(p - s.first, base) / norm(base);
  return s.first + base * r;
}

// 反射: 点pを直線sと線対称に移動した点
Point reflection(Line s, Point p)
{
  return p + (projection(s, p) - p) * Point{2.0, 0.0};
}

Line vertical_bisector(Line x)
{
  Point now = (x.first + x.second) * Point{0.5, 0};
  return Line(now, now + (x.second - x.first) * Point{0, M_PI_2});
}

enum class Position
{
  COUNTER_CLOCKWISE, // 反時計回り
  CLOCKWISE,         // 時計回り
  ON_LINE_BACK,      // Lineの始点側に点がある
  ON_LINE_FRONT,     // Lineの終点側に点がある
  ON_SEGMENT         // Line上に点がある
};

// ccw: 線分sと点pの位置関係を示す
Position ccw(Line s, Point p)
{
  Point a = s.second - s.first, b = p - s.first;
  if (cross(a, b) > eps)
    return Position::COUNTER_CLOCKWISE;
  if (cross(a, b) < -eps)
    return Position::CLOCKWISE;
  if (dot(a, b) < -eps)
    return Position::ON_LINE_BACK;
  if (norm(a) < norm(b))
    return Position::ON_LINE_FRONT;
  return Position::ON_SEGMENT;
}

// 平行判定
bool is_parallel(Point a, Point b) { return abs(cross(a, b)) < EPS; }
bool is_parallel(Line a, Line b) { return is_parallel(a.second - a.first, b.second - b.first); }

// 直交判定
bool is_orthogonal(Point a, Point b) { return abs(dot(a, b)) < EPS; }
bool is_orthogonal(Line a, Line b) { return is_orthogonal(a.second - a.first, b.second - b.first); }

// 交差判定
bool is_intersect_line(Line s1, Segment s2)
{
  if (cross(s1.second - s1.first, s2.first - s1.first) * cross(s1.second - s1.first, s2.second - s1.first) > eps)
  {
    return false;
  }
  if (ccw(s1, s2.first) == Position::ON_LINE_BACK and ccw(s1, s2.second) == Position::ON_LINE_BACK)
  {
    return false;
  }
  if (ccw(s1, s2.first) == Position::ON_LINE_FRONT and ccw(s1, s2.second) == Position::ON_LINE_FRONT)
  {
    return false;
  }
  return true;
}

bool is_intersect(Segment s1, Segment s2)
{
  for (int i = 0; i < 2; ++i)
  {
    if (!is_intersect_line(s1, s2))
    {
      return false;
    }
    swap(s1, s2);
  }
  return true;
}

bool is_intersect(Polygon s1, Polygon s2)
{
  for (int i = 0; i < s1.size(); ++i)
  {
    for (int q = 0; q < s2.size(); ++q)
    {
      if (is_intersect(Segment{s1[i], s1[(i + 1) % s1.size()]}, Segment{s2[q], s2[(q + 1) % s2.size()]}))
        return true;
    }
  }
  return false;
}

// 交差点
Point intersection_point(Line s1, Line s2)
{
  ld s, t;
  ld deno = cross(s1.second - s1.first, s2.second - s2.first) + eps;
  s = cross(s2.first - s1.first, s2.second - s2.first) / deno;
  return s1.first + s * (s1.second - s1.first);
}

//線分と点の距離
ld distance(Segment s, Point p)
{
  if (dot(s.second - s.first, p - s.first) < eps)
    return abs(p - s.first);
  if (dot(s.first - s.second, p - s.second) < eps)
    return abs(p - s.second);
  return abs(cross(s.second - s.first, p - s.first)) / abs(s);
}

//線分と線分の距離
ld distance(Segment s1, Segment s2)
{
  if (is_intersect(s1, s2))
  {
    return 0;
  }
  return min({distance(s1, s2.first), distance(s1, s2.second), distance(s2, s1.first), distance(s2, s1.second)});
}
//多角形の面積
ld area(Polygon poly)
{
  ld ans = 0;
  for (int i = 0; i < poly.size(); ++i)
  {
    Point a = poly[i], b = poly[(i + 1) % poly.size()];
    ans += cross(a, b);
  }
  ans /= 2.0L;
  return abs(ans);
}

//凸多角形か判定
bool is_convex(Polygon poly)
{
  for (int i = 0; i < poly.size(); ++i)
  {
    Line a = {poly[i], poly[(i + 1) % poly.size()]};
    if (ccw(a, poly[(i + 2) % poly.size()]) == Position::CLOCKWISE)
      return false;
  }
  return true;
}

//多角形上に点があるか判定
bool is_on_polygon(Polygon poly, Point p)
{
  for (int i = 0; i < poly.size(); ++i)
  {
    Line a = {poly[i], poly[(i + 1) % poly.size()]};
    if (ccw(a, p) == Position::ON_SEGMENT)
      return true;
  }
  return false;
}

//多角形内に点があるか判定
bool is_inside_polygon(Polygon poly, Point p)
{
  if (is_on_polygon(poly, p))
    return true;
  const int n = poly.size();
  int wn = 0;
  for (int i = 0; i < n; ++i)
  {
    ld vt = (p.imag() - poly[i].imag()) / (poly[(i + 1) % n].imag() - poly[i].imag());
    if (p.real() < (poly[i].real() + vt * (poly[(i + 1) % n].real() - poly[i].real())))
    {
      if ((poly[i].imag() <= p.imag()) and (poly[(i + 1) % n].imag() > p.imag()))
      {
        wn++;
      }
      else if ((poly[i].imag() > p.imag()) and (poly[(i + 1) % n].imag() <= p.imag()))
      {
        wn--;
      }
    }
  }
  if (wn != 0)
    return true;
  return false;
}

// 凸包
Polygon convex_hull(Polygon poly)
{
  if (poly.size() <= 1)
    return poly;
  sort(ALL(poly), [](auto &l, auto &r)
       {
    if(l.real() != r.real()) return l.real() < r.real();
    return l.imag() < r.imag(); });
  Polygon ans;
  ans.push_back(poly[0]);
  ans.push_back(poly[1]);
  for (int i = 2; i < poly.size(); ++i)
  {
    while (ans.size() >= 2)
    {
      Point x = ans[ans.size() - 2];
      Point y = ans[ans.size() - 1];
      if (ccw({x, y}, poly[i]) == Position::COUNTER_CLOCKWISE)
      {
        ans.pop_back();
      }
      else
        break;
    }
    ans.push_back(poly[i]);
  }

  Polygon reversed_ans;
  reversed_ans.push_back(poly[0]);
  reversed_ans.push_back(poly[1]);
  for (int i = 2; i < poly.size(); ++i)
  {
    while (reversed_ans.size() >= 2)
    {
      Point x = reversed_ans[reversed_ans.size() - 2];
      Point y = reversed_ans[reversed_ans.size() - 1];
      if (ccw({x, y}, poly[i]) == Position::CLOCKWISE)
      {
        reversed_ans.pop_back();
      }
      else
        break;
    }
    reversed_ans.push_back(poly[i]);
  }
  for (int q = reversed_ans.size() - 2; q >= 1; --q)
  {
    ans.push_back(reversed_ans[q]);
  }
  return ans;
}

// 凸多角形の直径
ld diameter(Polygon poly)
{
  ld ans = 0;
  int itr = 0;
  REP(i, poly.size())
  {
    if (abs(poly[i] - poly[0]) > abs(poly[itr] - poly[0]))
    {
      itr = i;
    }
  }
  REP(i, poly.size())
  {
    while (abs(poly[(itr + 1) % poly.size()] - poly[i]) > abs(poly[itr] - poly[i]))
    {
      itr++;
      itr %= poly.size();
    }
    ans = max(ans, abs(poly[itr] - poly[i]));
  }
  return ans;
}

// 凸多角形の切断
Polygon convex_cut(Polygon poly, Line l)
{
  Polygon ans;
  for (int i = 0; i < poly.size(); ++i)
  {
    Point now = poly[i];
    Point nxt = poly[(i + 1) % poly.size()];
    if (ccw(l, now) != Position::CLOCKWISE)
    {
      ans.push_back(now);
    }
    if (is_intersect_line(l, {now, nxt}))
    {
      ans.push_back(intersection_point(l, {now, nxt}));
    }
  }
  return ans;
}
#line 17 "Source.cpp"

#define int long long

void solve()
{
  int n, m;
  cin >> n >> m;
  if (n == 0)
    exit(0);
  Polygon x, y;
  REP(i, 2)
  {
    REP(q, n)
    {
      ld a, b;
      cin >> a >> b;
      x.push_back({a, b});
    }
    swap(x, y);
    swap(n, m);
  }

  x = convex_hull(x);
  y = convex_hull(y);
  if (is_intersect(x, y))
  {
    cout << "NO" << endl;
  }
  else
  {
    for (auto t : x)
    {
      if (is_inside_polygon(y, t))
      {
        cout << "NO" << endl;
        return;
      }
    }
    for (auto t : y)
    {
      if (is_inside_polygon(x, t))
      {
        cout << "NO" << endl;
        return;
      }
    }
    cout << "YES" << endl;
  }
}

#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(10);
  // scanf/printf user should delete this fasterize input/output script

  int t = 1000;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3492
final_rank: 12

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline ll time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

const long double eps = 1e-13;

struct point{
    ll x,y;
    point() {}
    point(ll x,ll y): x(x), y(y) {}
    point& operator-=(const point &p){
        x -= p.x; y -= p.y;
        return *this;
    }
    point& operator+=(const point &p){
        x += p.x; y += p.y;
        return *this;
    }
    point& operator*=(ll d){
        x *= d; y *= d;
        return *this;
    }
    point& operator/=(ll d){
        x /= d; y /= d;
        return *this;
    }
    const point operator+ (const point& p) const;
    const point operator- (const point& p) const;
    const point operator* (ll d) const;
    const point operator/ (ll d) const;
};
const point point::operator+ (const point& p) const{
    point res(*this); return res += p;
}
const point point::operator- (const point& p) const{
    point res(*this); return res -= p;
}
const point point::operator* (ll d) const{
    point res(*this); return res *= d;
}
const point point::operator/ (ll d) const{
    point res(*this); return res /= d;
}

ll cross(point a,point b){
    return a.x*b.y-a.y*b.x;
}

// 2色の頂点群を、各領域に含まれる色が単色になるように、直線で分割できるか判定
// (ただし、直線上に頂点は含まない)
// 入力が格子点の場合、整数範囲で処理できる
// vの前半は頂点の座標で、後半は色を表す(0or1)
// O(N^3) ただ枝狩りが結構効く気がする
// verify
// AOJ-1298 CC-FLIPOINTS
bool can_separate_points(vector<pair<point,bool>> &v){
    int n = v.size();
    vector<pair<point,bool>> u;
    // 2点決め打ち
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            
            // 外積の値を見て直線上のどっち側or直線上にあるか分類
            int b = 0, w = 0;
            u.clear();
            auto p1 = v[i].first;
            auto p2 = v[j].first;
            for(int k=0;k<n;k++){
                if(i == k or j == k){
                    u.push_back(v[k]);
                    continue;
                }
                auto p = v[k].first;
                ll cr = cross(p2-p1, p-p1);
                if(cr == 0){
                    u.push_back(v[k]);
                }
                else if(cr > 0){
                    b |= (1<<v[k].second);
                }
                else if(cr < 0){
                    w |= (1<<v[k].second);
                }
                // 枝狩り
                if(b == 3 or w == 3 or (b&w)) break;
            }
            if(b == 3 or w == 3 or (b&w)) continue;

            // 適当な基準でソートする
            sort(u.begin(), u.end(), [&](auto i, auto j){
                auto p1 = i.first;
                auto p2 = j.first;
                if(p1.x != p2.x) return p1.x < p2.x;
                else return p1.y < p2.y;
            });

            // 決め打った直線上の点に関して、色の入れ替わる回数が1回以下ならOK
            // 逆にそうでないなら、分割不可能(枝狩りポイント)
            int cnt = 0;
            for(int k=0;k+1<u.size();k++){
                if(u[k].second != u[k+1].second) cnt++;
            }
            return (cnt <= 1);
        }
    }
    return false;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m;
    while(cin >> n >> m, n+m){
        vector<pair<point,bool>> v(n+m);
        for(int i=0;i<n+m;i++){
            cin >> v[i].first.x >> v[i].first.y;
            v[i].second = (i<n);
        }
        if(can_separate_points(v)){
            printf("YES\n");
        }
        else{
            printf("NO\n");
        }
    }
}
accuracy: 1
time_ms: 80
memory_kb: 3168
final_rank: 1

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline ll time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

const long double eps = 1e-13;

struct point{
    ll x,y;
    point() {}
    point(ll x,ll y): x(x), y(y) {}
    point& operator-=(const point &p){
        x -= p.x; y -= p.y;
        return *this;
    }
    point& operator+=(const point &p){
        x += p.x; y += p.y;
        return *this;
    }
    point& operator*=(ll d){
        x *= d; y *= d;
        return *this;
    }
    point& operator/=(ll d){
        x /= d; y /= d;
        return *this;
    }
    const point operator+ (const point& p) const;
    const point operator- (const point& p) const;
    const point operator* (ll d) const;
    const point operator/ (ll d) const;
};
const point point::operator+ (const point& p) const{
    point res(*this); return res += p;
}
const point point::operator- (const point& p) const{
    point res(*this); return res -= p;
}
const point point::operator* (ll d) const{
    point res(*this); return res *= d;
}
const point point::operator/ (ll d) const{
    point res(*this); return res /= d;
}

ll cross(point a,point b){
    return a.x*b.y-a.y*b.x;
}

// 2色の頂点群を、各領域に含まれる色が単色になるように、直線で分割できるか判定
// (ただし、直線上に頂点は含まない)
// 入力が格子点の場合、整数範囲で処理できる
// vの前半は頂点の座標で、後半は色を表す(0or1)
// O(N^3) ただ枝狩りが結構効く気がする
// verify
// AOJ-1298 CC-FLIPOINTS
bool can_separate_points(vector<pair<point,bool>> &v){
    int n = v.size();
    vector<pair<point,bool>> u;
    // 2点決め打ち
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            // 外積の値を見て直線上のどっち側or直線上にあるか分類
            int b = 0, w = 0;
            u.clear();
            auto p1 = v[i].first;
            auto p2 = v[j].first;
            for(int k=0;k<n;k++){
                if(i == k or j == k){
                    u.push_back(v[k]);
                    continue;
                }
                auto p = v[k].first;
                ll cr = cross(p2-p1, p-p1);
                if(cr == 0){
                    u.push_back(v[k]);
                }
                else if(cr > 0){
                    b |= (1<<v[k].second);
                }
                else if(cr < 0){
                    w |= (1<<v[k].second);
                }
                // 枝狩り
                if(b == 3 or w == 3 or (b&w)) break;
            }
            if(b == 3 or w == 3 or (b&w)) continue;

            // 適当な基準でソートする
            sort(u.begin(), u.end(), [&](auto i, auto j){
                auto p1 = i.first;
                auto p2 = j.first;
                if(p1.x != p2.x) return p1.x < p2.x;
                else return p1.y < p2.y;
            });

            // 決め打った直線上の点に関して、色の入れ替わる回数が1回以下ならOK
            // 逆にそうでないなら、分割不可能(枝狩りポイント)
            int cnt = 0;
            for(int k=0;k+1<u.size();k++){
                if(u[k].second != u[k+1].second) cnt++;
            }
            return (cnt <= 1);
        }
    }
    return false;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m;
    while(cin >> n >> m, n+m){
        vector<pair<point,bool>> v(n+m);
        for(int i=0;i<n+m;i++){
            cin >> v[i].first.x >> v[i].first.y;
            v[i].second = (i<n);
        }
        if(can_separate_points(v)){
            printf("YES\n");
        }
        else{
            printf("NO\n");
        }
    }
}
accuracy: 1
time_ms: 80
memory_kb: 3392
final_rank: 4

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline ll time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

const long double eps = 1e-13;

struct point{
    ll x,y;
    point() {}
    point(ll x,ll y): x(x), y(y) {}
    point& operator-=(const point &p){
        x -= p.x; y -= p.y;
        return *this;
    }
    point& operator+=(const point &p){
        x += p.x; y += p.y;
        return *this;
    }
    point& operator*=(ll d){
        x *= d; y *= d;
        return *this;
    }
    point& operator/=(ll d){
        x /= d; y /= d;
        return *this;
    }
    const point operator+ (const point& p) const;
    const point operator- (const point& p) const;
    const point operator* (ll d) const;
    const point operator/ (ll d) const;
};
const point point::operator+ (const point& p) const{
    point res(*this); return res += p;
}
const point point::operator- (const point& p) const{
    point res(*this); return res -= p;
}
const point point::operator* (ll d) const{
    point res(*this); return res *= d;
}
const point point::operator/ (ll d) const{
    point res(*this); return res /= d;
}

ll cross(point a,point b){
    return a.x*b.y-a.y*b.x;
}

// 2色の頂点群を、各領域に含まれる色が単色になるように、直線で分割できるか判定
// (ただし、直線上に頂点は含まない)
// 入力が格子点の場合、整数範囲で処理できる
// vの前半は頂点の座標で、後半は色を表す(0or1)
// O(N^3) ただ枝狩りが結構効く気がする
// verify
// AOJ-1298 CC-FLIPOINTS
bool can_separate_points(vector<pair<point,int>> &v){
    int n = v.size();
    vector<pair<point,int>> u;
    // 2点決め打ち
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            // 外積の値を見て直線上のどっち側or直線上にあるか分類
            int b = 0, w = 0;
            u.clear();
            auto p1 = v[i].first;
            auto p2 = v[j].first;
            for(int k=0;k<n;k++){
                if(i == k or j == k){
                    u.push_back(v[k]);
                    continue;
                }
                auto p = v[k].first;
                ll cr = cross(p2-p1, p-p1);
                if(cr == 0){
                    u.push_back(v[k]);
                }
                else if(cr > 0){
                    b |= (1<<v[k].second);
                }
                else if(cr < 0){
                    w |= (1<<v[k].second);
                }
                // 枝狩り
                if(b == 3 or w == 3 or (b&w)) break;
            }
            if(b == 3 or w == 3 or (b&w)) continue;

            // 適当な基準でソートする
            sort(u.begin(), u.end(), [&](auto i, auto j){
                auto p1 = i.first;
                auto p2 = j.first;
                if(p1.x != p2.x) return p1.x < p2.x;
                else return p1.y < p2.y;
            });

            // 決め打った直線上の点に関して、色の入れ替わる回数が1回以下ならOK
            // 逆にそうでないなら、分割不可能(枝狩りポイント)
            int cnt = 0;
            for(int k=0;k+1<u.size();k++){
                if(u[k].second != u[k+1].second) cnt++;
            }
            return (cnt <= 1);
        }
    }
    return false;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m;
    while(cin >> n >> m, n+m){
        vector<pair<point,int>> v(n+m);
        for(int i=0;i<n+m;i++){
            cin >> v[i].first.x >> v[i].first.y;
            v[i].second = (i<n);
        }
        if(can_separate_points(v)){
            printf("YES\n");
        }
        else{
            printf("NO\n");
        }
    }
}
accuracy: 1
time_ms: 90
memory_kb: 3392
final_rank: 5

code_snippet: #line 1 "c.cpp"
/*	author:  Kite_kuma
	created: 2022.03.01 11:03:30 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#line 8 "Library/Math/Geometry_light.hpp"

#pragma region geometry_light

using Real = long double;
using R = Real;
using Point = std::complex<Real>;
using Vec = Point;
const Real EPS = 1e-10, PI = acos(-1);

inline bool eq(const Real &a, const Real &b) { return fabs(b - a) < EPS; }
inline bool eq(const Point &a, const Point &b) { return fabs(b - a) < EPS; }
/*
	-1: a < b
	0 : a == b
	1 : a > b
*/
inline int compare(const Real &a, const Real &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; }
inline int sign(const Real &a) { return fabs(a) < EPS ? 0 : a < 0 ? -1 : 1; }

namespace std {
const Point operator*(const Point &p, const Real &d) { return Point(real(p) * d, imag(p) * d); }
}  // namespace std

std::istream &operator>>(std::istream &is, Point &p) {
	Real a, b;
	is >> a >> b;
	p = Point(a, b);
	return is;
}
std::ostream &operator<<(std::ostream &os, Point &p) { return os << std::fixed << std::setprecision(10) << p.real() << " " << p.imag(); }

// rotate point 'p' for counter clockwise direction
const Point rotate(const Real &theta, const Point &p) {
	return Point(cos(theta) * p.real() - sin(theta) * p.imag(), sin(theta) * p.real() + cos(theta) * p.imag());
}

const Real radian_to_degree(const Real &r) { return (r * 180.0 / PI); }

const Real degree_to_radian(const Real &d) { return (d * PI / 180.0); }

// get angle a-b-c (<pi)
const Real get_angle(const Point &a, const Point &b, const Point &c) {
	const Point v(a - b), w(c - b);
	Real theta = fabs(atan2(w.imag(), w.real()) - atan2(v.imag(), v.real()));
	return std::min(theta, 2 * PI - theta);
}

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

struct Line {
	Point a, b;

	Line() = default;

	Line(Point a, Point b) : a(a), b(b) {}

	Line(Real A, Real B, Real C)  // Ax + By = C
	{
		if(eq(A, 0))
			a = Point(0, C / B), b = Point(1, C / B);
		else if(eq(B, 0))
			b = Point(C / A, 0), b = Point(C / A, 1);
		else
			a = Point(0, C / B), b = Point(C / A, 0);
	}

	friend std::ostream &operator<<(std::ostream &os, Line &p) { return os << p.a << " -- " << p.b; }

	friend std::istream &operator>>(std::istream &is, Line &a) { return is >> a.a >> a.b; }
};

struct Segment : Line {
	Segment() = default;

	Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
	Point p;
	Real r;

	Circle() = default;

	Circle(Point p, Real r) : p(p), r(r) {}
};

using Points = std::vector<Point>;
using Polygon = std::vector<Point>;
using Segments = std::vector<Segment>;
using Lines = std::vector<Line>;
using Circles = std::vector<Circle>;

const Real cross(const Point &a, const Point &b) { return real(a) * imag(b) - imag(a) * real(b); }
const Real dot(const Point &a, const Point &b) { return real(a) * real(b) + imag(a) * imag(b); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
const int ccw(const Point &a, Point b, Point c) {
	b = b - a, c = c - a;
	if(cross(b, c) > EPS) return +1;		// "COUNTER_CLOCKWISE"
	if(cross(b, c) < -EPS) return -1;		// "CLOCKWISE"
	if(dot(b, c) < -EPS) return +2;			// "ONLINE_BACK"
	if(norm(b) + EPS < norm(c)) return -2;	// "ONLINE_FRONT"
	return 0;								// "ON_SEGMENT"
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool parallel(const Line &a, const Line &b) { return eq(cross(a.b - a.a, b.b - b.a), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool orthogonal(const Line &a, const Line &b) { return eq(dot(a.a - a.b, b.a - b.b), 0.0); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point projection(const Line &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p) {
	double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + (l.a - l.b) * t;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflection(const Line &l, const Point &p) { return projection(l, p) * 2.0 - p; }

int intersect(const Line &l, const Point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); }

int intersect(const Line &l, const Line &m) {
	if(intersect(l, m.a) && intersect(l, m.b)) return -1;
	return int(abs(cross(l.b - l.a, m.b - m.a)) > EPS);
}

int intersect(const Segment &s, const Point &p) { return int(ccw(s.a, s.b, p) == 0); }

int intersect(const Line &l, const Segment &s) {
	if(intersect(l, s.a) && intersect(l, s.b)) return -1;
	return cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < EPS;
}

Real distance(const Line &l, const Point &p);

int intersect(const Circle &c, const Line &l) {
	Real d = c.r - distance(l, c.p);
	return fabs(d) < EPS ? 1 : d > 0. ? 2 : 0;
}

int intersect(const Circle &c, const Point &p) { return int(abs(abs(p - c.p) - c.r) < EPS); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
int intersect(const Segment &s, const Segment &t) {
	if(eq(s.a, s.b)) return intersect(t, s.a);
	if(intersect(Line(s), t.a) && intersect(Line(s), t.b) &&
	   std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b)))
		return -1;
	return int(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);
}

int intersect(const Circle &c, const Segment &l) {
	const Point h = projection(l, c.p);
	if(norm(h - c.p) - c.r * c.r > EPS) return 0;
	auto d1 = abs(c.p - l.a), d2 = abs(c.p - l.b);
	if(compare(d1, c.r) == -1 && compare(d2, c.r) == -1) return 0;
	if(d1 < c.r - EPS && d2 > c.r - EPS || d1 > c.r - EPS && d2 < c.r - EPS) return 1;
	return dot(l.a - h, l.b - h) < 0 ? 2 : 0;
}

Real distance(const Point &a, const Point &b);

int number_of_common_tangents(const Circle &c1, const Circle &c2) {
	Real r1 = std::min(c1.r, c2.r), r2 = std::max(c1.r, c2.r), d = distance(c1.p, c2.p);
	int com = compare(r1 + r2, d);
	return com == 1 ? compare(d + r1, r2) + 1 : 3 - com;
	// if(c1.r < c2.r) swap(c1, c2);
	// Real d = abs(c1.p - c2.p);
	// if(compare(c1.r + c2.r, d) == -1) return 4;
	// if(eq(c1.r + c2.r, d)) return 3;
	// if(compare(c1.r - c2.r, d) == -1) return 2;
	// return int(eq(c1.r - c2.r, d));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
int intersect(const Circle &c1, const Circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); }

Real distance(const Point &a, const Point &b) { return abs(a - b); }

Real distance(const Line &l, const Point &p) { return abs(p - projection(l, p)); }

Real distance(const Line &l, const Line &m) { return intersect(l, m) ? 0 : distance(l, m.a); }

Real distance(const Segment &s, const Point &p) {
	Point r = projection(s, p);
	return intersect(s, r) ? distance(r, p) : std::min(abs(s.a - p), abs(s.b - p));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D
Real distance(const Segment &a, const Segment &b) {
	if(intersect(a, b)) return 0;
	return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}

Real distance(const Line &l, const Segment &s) {
	if(intersect(l, s)) return 0;
	return std::min(distance(l, s.a), distance(l, s.b));
}

Point crosspoint(const Line &l, const Line &m) {
	Real A = cross(l.b - l.a, m.b - m.a);
	Real B = cross(l.b - l.a, l.b - m.a);
	if(eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
	return m.a + (m.b - m.a) * B / A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C
Point crosspoint(const Segment &l, const Segment &m) { return crosspoint(Line(l), Line(m)); }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
std::pair<Point, Point> crosspoint(const Circle &c, const Line l) {
	Point pr = projection(l, c.p);
	if(eq(distance(l, c.p), c.r)) return {pr, pr};
	Vec v = (l.b - l.a) / abs(l.b - l.a) * sqrt(c.r * c.r - norm(pr - c.p));
	return make_pair(pr - v, pr + v);
	// Vec e = (l.b - l.a) / abs(l.b - l.a);
	// double base = sqrt(c.r * c.r - norm(pr - c.p));
	// return {pr - e * base, pr + e * base};
}

std::pair<Point, Point> crosspoint(const Circle &c, const Segment &l) {
	if(intersect(c, l) == 2) return crosspoint(c, Line(l.a, l.b));
	auto ret = crosspoint(c, Line(l.a, l.b));
	if(dot(l.a - ret.first, l.b - ret.first) < EPS)
		ret.second = ret.first;
	else
		ret.first = ret.second;
	return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
std::pair<Point, Point> crosspoint(const Circle &c1, const Circle &c2) {
	Real d = abs(c1.p - c2.p);
	Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));  // cosine theorem
	Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
	Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
	return make_pair(p1, p2);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F
// "点 p を通る円 c の接線"の接点2つ
std::pair<Point, Point> tangent(const Circle &c1, const Point &p2) {
	return crosspoint(c1, Circle(p2, sqrt(norm(c1.p - p2) - c1.r * c1.r)));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
// 円 c1, c2 の共通接線
Lines tangent(Circle c1, Circle c2) {
	Lines ret;
	if(c1.r < c2.r) std::swap(c1, c2);
	Real g = norm(c1.p - c2.p);
	if(eq(g, 0)) return ret;
	Vec u = (c2.p - c1.p) / Real(sqrt(g));
	Vec v = rotate(PI * 0.5, u);
	for(int s : {-1, 1}) {
		Real h = (c1.r + s * c2.r) / sqrt(g);
		if(eq(1 - h * h, 0)) {
			ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
		} else if(1 - h * h > 0) {
			Point uu = u * h, vv = v * sqrt(1 - h * h);
			ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
			ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
		}
	}
	return ret;
}

#pragma endregion
#line 553 "c.cpp"

bool solve(int n) {
	int m;
	cin >> m;
	Points black, white;
	const R alpha = 1;
	rep(n) {
		Point p;
		cin >> p;
		p = rotate(alpha, p);
		black.push_back(p);
	}
	rep(m) {
		Point p;
		cin >> p;
		p = rotate(alpha, p);
		white.push_back(p);
	}

	auto judge = [&](int b, int w, int blackside) {
		// int black_sign = 0; // undetermined;
		// const Line ln(black[b], white[w]);
		foa(blackpt, black) {
			if(eq(blackpt, black[b])) continue;
			int c = (ccw(black[b], white[w], blackpt));
			if(c % 2 && blackside != c) return false;
			if(c % 2 == 0 && c != 2) return false;
		}
		foa(whitept, white) {
			if(eq(whitept, white[w])) continue;
			int c = (ccw(black[b], white[w], whitept));
			if(c % 2 && blackside == c) return false;
			if(c % 2 == 0 && c != -2) return false;
		}
		return true;
	};

	for(int bside = -1; bside < 2; bside += 2) {
		for(int b = 0; b < n; b++)
			for(int w = 0; w < m; w++) {
				if(judge(b, w, bside)) return true;
			}
	}

	return false;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) YES(solve(n));

	return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 3848
final_rank: 19

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,...) for(int i = (a)*(strlen(#__VA_ARGS__)!=0);i<(int)(strlen(#__VA_ARGS__)?__VA_ARGS__:(a));++i)
#define per(i,a,...) for(int i = (strlen(#__VA_ARGS__)?__VA_ARGS__:(a))-1;i>=(int)(strlen(#__VA_ARGS__)?(a):0);--i)
#define foreach(i, n) for(auto &i:(n))
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
#define lambda(RES_TYPE, ...) (function<RES_TYPE(__VA_ARGS__)>)[&](__VA_ARGS__) -> RES_TYPE
#define method(FUNC_NAME, RES_TYPE, ...) function<RES_TYPE(__VA_ARGS__)> FUNC_NAME = lambda(RES_TYPE, __VA_ARGS__)
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
//const ll MOD = (ll)1e9+7;
const ll MOD = 998244353;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}
#ifdef DEBUG
#define debug(x) cout<<"LINE "<<__LINE__<<": "<<#x<<" = "<<x<<endl;
#else
#define debug(x) (void)0
#endif

namespace templates{
    ll modpow(ll x, ll b,ll mod=MOD){
        ll res = 1;
        while(b){
            if(b&1)res = res * x % mod;
            x = x * x % mod;
            b>>=1;
        }
        return res;
    }

    ll modinv(ll x){
        return modpow(x, MOD-2);
    }

    bool was_output = false;

    void print();
    template <class t> void print(const vector<t> &);
    template <class t, class u> void print(const pair<t, u> &);
    template <class t> void print(const t&);
    template <class Head, class... Tail> void print(const Head&, const Tail&...);

    template <class t> void println(const vector<vector<t>>&);
    template <class t> void println(const vector<t>&);
    template <class t> void println(const t&);
    template <class Head, class... Tail> void println(const Head&, const Tail&...);
    void println();
    void newline();

    void print(){
        return;
    }

    template <class t>
    void print(const vector<t>&x){
        for(const t&i:x)print(i);
    }
    template <class t, class u>
    void print(const pair<t,u>&p){
        print(p.first);
        print(p.second);
    }
    template <class t>
    void print(const t&x){
        if(was_output)cout<<" ";
        cout<<x;
        was_output = true;
    }
    template <class Head, class... Tail>
    void print(const Head&head,const Tail&...tail){
        print(head);
        print(tail...);
    }

    template<class t>
    void println(const vector<vector<t>>&x){
        for(vector<t> i:x)println(i);
    }
    template<class t>
    void println(const vector<t>&x){
        for(const t&i:x)print(i);
        println();
    }
    template <class t>
    void println(const t&x){
        print(x);
        println();
    }
    void println(){
        if(was_output){
            cout << endl;
            was_output = false;
        }
    }
    template <class Head, class... Tail>
    void println(const Head&head,const Tail&...tail){
        print(head);
        println(tail...);
    }

    void newline(){
        was_output = true;
        println();
    }

    template<class t>
    istream& operator>>(istream&is, vector<t>&x){
        for(auto &i:x)is >> i;
        return is;
    }

    template<class t, class u>
    istream& operator>>(istream&is, pair<t, u>&x){
        is >> x.first >> x.second;
        return is;
    }

    template<class t>
    ostream& operator<<(ostream&os, vector<t> &v){
        os << "{";
        for(t &i:v){
            os << i << ", ";
        }
        os << "}";
        return os;
    }

    template<class t = long long>
    t in(){
        t res; cin >> res; return res;
    }

    template<class t>
    vector<t> sorted(vector<t> line,function<bool(t,t)> comp=[](t a,t b){return a<b;}){
        sort(line.begin(),line.end(),comp);
        return line;
    }

    template<class t>
    vector<t> reversed(vector<t> line){
        reverse(line.begin(),line.end());
        return line;
    }
    string reversed(string str){
        reverse(str.begin(),str.end());
        return str;
    }

    long long gcd(long long a,long long b){
        while(b){
            a %= b;
            swap(a,b);
        }
        return a;
    }

    long long lcm(long long a,long long b){
        return a / gcd(a,b) * b;
    }

    class output_initializer{
    public:
        output_initializer(){
            ios::sync_with_stdio(false);
            cin.tie(nullptr);
            cout << setprecision(20);
        }
    };output_initializer OUTPUT_INITIALIZER_INSTANCE = output_initializer();
}

using namespace templates;

using C = complex<ll>;
using CC = complex<double>;

const double EPS = 1e-6;

template<class t>
t cross(complex<t> a,complex<t> b){
    return a.real() * b.imag() - a.imag() * b.real();
}
template<class t>
t dot(complex<t> a,complex<t> b){
    return a.real() * b.real() - a.imag() * b.imag();
}

CC toCC(C a){
    return CC(a.real(),a.imag());
}

vector<C> myconvex(vector<C> line){
    int n = line.size();
    if(n<=2)return line;
    vector<bool> flag(n,false);
    rep(i,n){
        rep(j,i+1,n){
            int ac = 0;
            int bc = 0;
            rep(k,n){
                if(i==k or j==k)continue;
                ll v = cross(line[i]-line[j],line[k]-line[j]);
                if(v < 0)++ac;
                if(v > 0)++bc;
            }
            if(ac==0 or bc==0){
                flag[i] = true;
                flag[j] = true;
            }
        }
    }
    CC mid;
    foreach(i,line)mid += toCC(i);
    mid /= n;
    vector<C> res;
    rep(i,n){
        if(flag[i])res.emplace_back(line[i]);
    }
    sort(all(res),lambda(bool,C a,C b){
            return arg(toCC(a)-mid) < arg(toCC(b)-mid);
        });
    return res;
}

bool func(int n,int m){
    vector<C> a;
    vector<C> b;
    rep(i,n){
        int x = in();
        int y = in();
        a.emplace_back(x,y);
    }
    rep(i,m){
        int x = in();
        int y = in();
        b.emplace_back(x,y);
    }
    a = myconvex(a);
    b = myconvex(b);
    method(check1,bool,C a,vector<C> line){
        int n = line.size();
        {
            double sum = 0;
            rep(i,n){
                sum += arg(toCC((line[(i+1)%n]-a))/toCC((line[i]-a)));
            }
            if(abs(sum) > 0.5)return true;
        }
        rep(i,n){
            C u = line[i];
            C v = line[(i+1)%n];
            if(cross(a-u,v-u)==0 and 0 <= dot(a-u,v-u) and dot(a-u,v-u) <= dot(v-u,v-u))return true;
        }
        return false;
    };
    method(check2,bool,C a,C b,C c,C d){
        if(0 <= cross(b-a,c-a) * cross(b-a,d-a))return false;
        if(0 <= cross(d-c,a-c) * cross(d-c,b-c))return false;
        return true;
    };
    n = a.size();
    m = b.size();
    if(n==1 and m==1)return true;
    foreach(i,a)if(check1(i,b))return false;
    foreach(i,b)if(check1(i,a))return false;
    rep(i,n){
        rep(j,m){
            if(check2(a[i],a[(i+1)%n],b[j],b[(j+1)%m]))return false;
        }
    }
    return true;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(true){
        int n = in();
        int m = in();
        if(n==0 and m==0)break;
        println(func(n,m) ? "YES" : "NO");
    }
    return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 3796
final_rank: 18