Problem:
Addition on Convex Polygons
Mr. Convexman likes convex polygons very much.
During his study on convex polygons, he has come up with the following elegant addition on convex polygons.
The sum of two points in the
xy
-plane,
(
x
1
,
y
1
) and
(
x
2
,
y
2
)
is defined as
(
x
1
+
x
2
,
y
1
+
y
2
).

A polygon is treated as the set of all the points on its
boundary and in its inside.
Here, the sum of two polygons
S
1
and
S
2
,
S
1
+
S
2
, is defined as
the set of all the points
v
1
+
v
2
satisfying
v
1
∈
S
1
and
v
2
∈
S
2
.
Sums of two convex polygons, thus defined, are always convex polygons!
The multiplication of a non-negative integer and a polygon is defined inductively by
0
S
= {(0, 0)} and, for a positive integer
k
,
kS
= (
k
- 1)
S
+
S
.
In this problem, line segments and points are also considered as convex polygons.
Mr. Convexman made many convex polygons based on two convex polygons
P
and
Q
to study properties of the addition, but one
day, he threw away by mistake the piece of paper on which he had written
down the vertex positions of the two polygons and the calculation process.
What remains at hand are only the vertex positions of two
convex polygons
R
and
S
that are represented as
linear combinations of
P
and
Q
with non-negative integer coefficients:
R
=
aP
+
bQ
, and
S
=
cP
+
dQ
.
Fortunately, he remembers that the coordinates of all vertices of
P
and
Q
are integers
and the coefficients
a
,
b
,
c
and
d
satisfy
ad
-
bc
= 1.
Mr. Convexman has requested you, a programmer and his friend, to make a program to recover
P
and
Q
from
R
and
S
,
that is, he wants you to, for given convex polygons
R
and
S
, compute non-negative integers
a
,
b
,
c
,
d
(
ad
-
bc
= 1)
and two convex polygons
P
and
Q
with vertices on integer points satisfying the above equation.
The equation may have many solutions.
Make a program to compute the minimum possible sum of the areas of
P
and
Q
satisfying the equation.
Input
The input consists of at most 40 datasets, each in the following format.
n
m
x
1
y
1
...
x
n
y
n
x'
1
y'
1
...
x'
m
y'
m
n
is the number of vertices of the convex polygon
R
, and
m
is that of
S
.
n
and
m
are integers and satisfy 3 ≤
n
≤ 1000 and 3 ≤
m
≤ 1000.
(
x
i
,
y
i
) represents the coordinates of the
i
-th vertex of the convex polygon
R
and (
x'
i
,
y'
i
) represents that of
S
.
x
i
,
y
i
,
x'
i
and
y'
i
are integers between −10
6
and 10
6
, inclusive.
The vertices of each convex polygon are given in counterclockwise order.
Three different vertices of one convex polygon do not lie on a single line.
The end of the input is indicated by a line containing two zeros.
Output
For each dataset, output a single line containing an integer representing the double of the sum of the areas of
P
and
Q
.
Note that the areas are always integers when doubled because the coordinates of each vertex of
P
and
Q
are integers.
Sample Input
5 3
0 0
2 0
2 1
1 2
0 2
0 0
1 0
0 1
4 4
0 0
5 0
5 5
0 5
0 0
2 0
2 2
0 2
3 3
0 0
1 0
0 1
0 1
0 0
1 1
3 3
0 0
1 0
1 1
0 0
1 0
1 1
4 4
0
...(truncated)

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;

typedef long long LL;
typedef pair<LL,LL> pll;

pll add(const pll &a, const pll &b){
	return pll(a.first + b.first, a.second + b.second);
}

pll sub(const pll &a, const pll &b){
	return pll(a.first - b.first, a.second - b.second);
}

pll mul(LL t, const pll &a){
	return pll(a.first * t, a.second * t);
}

LL cross(const pll &a, const pll &b){
	return a.first * b.second - b.first * a.second;
}

LL div(const pll &a, const pll &b){
	if(b.first != 0){ return a.first / b.first; }
	return a.second / b.second;
}

vector<pll> input(int n){
	vector<pll> pts(n);
	for(int i = 0; i < n; ++i){
		cin >> pts[i].first >> pts[i].second;
	}
	rotate(pts.begin(), min_element(pts.begin(), pts.end()), pts.end());

	vector<pll> vec(n);
	for(int i = 0; i < n; ++i){
		vec[i] = sub(pts[i + 1], pts[i]);
	}
	vec[n - 1] = sub(pts[0], pts[n - 1]);
	return vec;
}

LL area(const vector<pll> &v){
	int n = v.size();
	pll p;
	LL s = 0;
	for(int i = 0; i < n; ++i){
		pll q = add(p, v[i]);
		s += cross(p, q);
		p = q;
	}
	return s;
}

int main(){
	int n, m;
	while(cin >> n >> m && n){
		vector<pll> v1 = input(n);
		vector<pll> v2 = input(m);
		if(area(v1) > area(v2)){ v1.swap(v2); }
		vector<int> idxs;
		while(true){
			int s1 = v1.size(), s2 = v2.size();
			idxs.assign(s1, -1);
			int j = 0;
			LL u = 1LL << 50;
			for(int i = 0; i < s1; ++i){
				for(; j < s2; ++j){
					if(cross(v1[i], v2[j]) == 0){ break; }
				}
				if(j >= s2){
					u = 0;
					break;
				}
				idxs[i] = j;
				LL t = div(v2[j], v1[i]);
				u = min(t, u);
				++j;
			}
			if(u <= 0){ break; }
			for(int i = 0; i < s1; ++i){
				int k = idxs[i];
				v2[k] = sub(v2[k], mul(u, v1[i]));
			}
			v2.erase(remove(v2.begin(), v2.end(), pll()), v2.end());
			v1.swap(v2);
		}
		LL a1 = area(v1);
		LL a2 = area(v2);
		cout << (a1 + a2) << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3400
final_rank: 3

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

using namespace std;
#define rep2(i, j, k) for(ll i=ll(j);i<ll(k);i++)
#define rep(i, j) rep2(i,0,j)
#define rrep2(i, j, k) for(ll i=ll(j)-1;i>=ll(k);i--)
#define rrep(i, j) rrep2(i,j,0)
#define eb emplace_back
#define all(a) a.begin(),a.end()
#define SZ(a) ll(a.size())
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vl>;
using P = pair<ll, ll>;
using vp = vector<P>;
using vvp = vector<vp>;

template<class T>
bool chmin(T &a, T b) { return a > b ? a = b, 1 : 0; }

template<class T>
bool chmax(T &a, T b) { return a < b ? a = b, 1 : 0; }

const ll inf = LLONG_MAX / 4;

pair<P, ll> decomp(ll x, ll y) {
    assert(x or y);
    ll g = gcd(abs(x), abs(y));
    return {P(x/g, y/g), g};
}

ll det(P a, P b) {
    return a.first * b.second - a.second * b.first;
}

bool cmp(P a, P b) {
    assert(a.first or a.second);
    assert(b.first or b.second);
    int ax = (a.second > 0 or (!a.second and a.first > 0));
    int bx = (b.second > 0 or (!b.second and b.first > 0));
    if(ax != bx) return ax < bx;
    return det(a, b) > 0;
}

P add(P a, P b) {
    return {a.first + b.first, a.second + b.second};
}

vector<vector<pair<P, P>>> path(P f) {
    assert(f.first >= 0 and f.second >= 0 and (f.first or f.second));
    assert(gcd(f.first, f.second) == 1);
    if(!f.first or !f.second) return {};
    P l = {0, 1}, r = {1, 0};
    vector<vector<pair<P, P>>> res;
    res.eb();
    res.back().eb(l, r);
    P m = add(l, r);
    while(m != f) {
        res.eb();
        if(cmp(m, f)) { // m > f
            do {
                r = m;
                m = add(l, r);
                res.back().eb(l, r);
            } while(cmp(m, f));
        } else { // m < f
            do {
                l = m;
                m = add(l, r);
                res.back().eb(l, r);
            } while(cmp(f, m));
        }
    }
    return res;
}

vp vecs;
vl r, s;

ll area(const vl &v) {
    assert(SZ(v) == SZ(vecs));
    ll res = 0;
    ll x = 0, y = 0;
    rep(i, SZ(v)) {
        ll nx = x + vecs[i].first * v[i];
        ll ny = y + vecs[i].second * v[i];
        res += det(P(x, y), P(nx, ny));
        x = nx;
        y = ny;
    }
    assert(!x and !y);
    return res;
}

void solve(int n, int m) {
    vecs.clear();
    map<P, P> cnt;
    rep(t, 2) {
        vl x(n+1), y(n+1);
        rep(i, n) cin >> x[i] >> y[i];
        x[n] = x[0];
        y[n] = y[0];
        rep(i, n) {
            auto [p, c] = decomp(x[i+1]-x[i], y[i+1]-y[i]);
            vecs.eb(p);
            if(!t) cnt[p].first += c;
            else cnt[p].second += c;
        }
        swap(n, m);
    }
    sort(all(vecs), cmp);
    vecs.erase(unique(all(vecs)), vecs.end());
    int sz = SZ(vecs);
    r.assign(sz, 0);
    s.assign(sz, 0);
    vp f(sz);
    rep(i, sz) {
        r[i] = cnt[vecs[i]].first;
        s[i] = cnt[vecs[i]].second;
        f[i] = decomp(r[i], s[i]).first;
    }
    sort(f.rbegin(), f.rend(), cmp);
    if(f[0] == f.back()) {
        vl v(sz);
        rep(i, sz) v[i] = r[i] / f[0].first;
        cout << area(v) << '\n';
        return;
    }
    ll ans = inf;
    auto calc = [&](pair<P, P> p) -> ll {
        if(cmp(p.first, f[0])) return inf;
        if(cmp(f.back(), p.second)) return inf;
        auto [b, d] = p.first;
        auto [a, c] = p.second;
        assert(a * d - b * c == 1);
        vl P(sz), Q(sz);
        rep(i, sz) {
            P[i] = d * r[i] - b * s[i];
            Q[i] = a * s[i] - c * r[i];
            assert(P[i] >= 0 and Q[i] >= 0);
        }
        return area(P) + area(Q);
    };
    chmin(ans, calc({P(0, 1), P(1, 0)}));
    for(const auto &v : path(f[0])) {
        assert(SZ(v) >= 1);
        rep(i, SZ(v)) chmin(ans, calc(v[i]));
    }
    for(const auto &v : path(f.back())) {
        assert(SZ(v) >= 1);
        rep(i, SZ(v)) chmin(ans, calc(v[i]));
    }
    if(det(f[0], f.back()) == -1) chmin(ans, calc({f[0], f.back()}));
    assert(ans != inf);
    cout << ans << '\n';
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int n, m;
    while(cin >> n >> m, n) solve(n, m);
}
accuracy: 1
time_ms: 90
memory_kb: 29048
final_rank: 7

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::pair<int, int> pi;
typedef std::vector<int> Vint;
typedef std::vector<bool> Vbool;
typedef std::vector<ld> Vld;
const ll INF = 1e17;
const int LEN = 1e5 + 1;
const ld TOL = 1e-7;
const ll MOD = 1'000'000'007;
int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
bool zero(const ld& x) { return !sign(x); }
ll sq(int x) { return (ll)x * x; }
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }

int T, N, M;
struct Pos {
	int x, y, i;
	Pos(int X = 0, int Y = 0, int I = 0) : x(X), y(Y), i(I) {}
	bool operator == (const Pos& p) const { return x == p.x && y == p.y; }
	bool operator != (const Pos& p) const { return x != p.x || y != p.y; }
	//bool operator < (const Pos& p) const { return x == p.x ? y < p.y : x < p.x; }
	bool operator < (const Pos& p) const { return x == p.x ? y == p.y ? i > p.i : y < p.y : x < p.x; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const int& n) const { return { x * n, y * n }; }
	Pos operator / (const int& n) const { return { x / n, y / n }; }
	ll operator * (const Pos& p) const { return (ll)x * p.x + (ll)y * p.y; }
	ll operator / (const Pos& p) const { return (ll)x * p.y - (ll)y * p.x; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const int& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const int& scale) { x /= scale; y /= scale; return *this; }
	ll Euc() const { return (ll)x * x + (ll)y * y; }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = Pos(0, 0);
typedef std::vector<Pos> Polygon;
ll cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ll cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
ll dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ll dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { ll ret = cross(d1, d2, d3); return ret < 0 ? -1 : !!ret; }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { ll ret = cross(d1, d2, d3, d4); return ret < 0 ? -1 : !!ret; }
bool same_dir(const Pos& p, const Pos& q) { return p * q >= 0 && p / q == 0; }
ll area(const Polygon& H) {
	ll ret = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) ret += H[i] / H[(i + 1) % sz];
	return ret;
}
void norm(Polygon& H) {
	ll A = area(H);
	if (A < 0) std::reverse(H.begin(), H.end());
	return;
}
void fit(Polygon& H) {
	auto p = std::min_element(H.begin(), H.end());
	std::rotate(H.begin(), p, H.end());
	return;
}
bool convex(Polygon& H) {
	int sz = H.size();
	for (int i = 0; i < sz; i++) {
		int i0 = (i - 1 + sz) % sz, i1 = i, i2 = (i + 1) % sz;
		if (ccw(H[i0], H[i1], H[i2]) <= 0) return 0;
	}
	return 1;
}
bool same_polygon(Polygon& R, Polygon& S) {
	fit(R); fit(S);
	int sz = R.size();
	if (sz != S.size()) return 0;
	Pos v = R[0] - S[0];
	for (Pos& p : S) p += v;
	for (int i = 0; i < sz; i++) if (R[i] != S[i]) return 0;
	return 1;
}
Polygon graham_scan(Polygon& C) {
	Polygon H;
	if (C.size() < 3) {
		std::sort(C.begin(), C.end());
		return C;
	}
	std::swap(C[0], *min_element(C.begin(), C.end()));
	std::sort(C.begin() + 1, C.end(), [&](const Pos& p, const Pos& q) -> bool {
		int ret = ccw(C[0], p, q);
		if (!ret) return (C[0] - p).Euc() < (C[0] - q).Euc();
		return ret > 0;
		}
	);
	C.erase(unique(C.begin(), C.end()), C.end());
	int sz = C.size();
	for (int i = 0; i < sz; i++) {
		while (H.size() >= 2 && ccw(H[H.size() - 2], H.back(), C[i]) <= 0)
			H.pop_back();
		H.push_back(C[i]);
	}
	return H;
}
bool minkowski_difference(Polygon& R, Polygon& S) {
	ll ar = area(R);
	ll as = area(S);
	if (ar == as) {
		if (same_polygon(R, S)) S.clear();
		return 0;
	}
	if (ar > as) std::swap(R, S);
	if (R.size() > S.size()) return 0;
	int sz = R.size();
	Vbool F(sz, 0);
	Polygon V;
	for (int i = 0; i < sz; i++) {
		Pos v = R[(i + 1) % sz] - R[i];
		int gcd_ = gcd(std::abs(v.x), std::abs(v.y));
		v /= gcd_;
		v.i = i;
		V.push_back(v);
	}
	sz = S.size();
	for (int i = 0; i < sz; i++) {
		Pos v = S[(i + 1) % sz] - S[i];
		int gcd_ = gcd(std::abs(v.x), std::abs(v.y));
		v /= gcd_;
		v.i = ~i;
		V.push_back(v);
	}
	int r = -1, s = -1;
	std::sort(V.begin(), V.end());
	sz = V.size();
	for (int i = 0; i < sz - 1; i++) {
		if (V[i] == V[i + 1]) {
			assert(V[i].i >= 0); assert(V[i + 1].i < 0);
			if (!~r) r = V[i].i, s = ~V[i + 1].i;
			F[V[i].i] = 1;
		}
	}
	if (!~r) return 0;
	sz = F.size();
	for (int i = 0; i < sz; i++) if (!F[i]) return 0;

	Polygon H;
	H.push_back(Pos(0, 0));
	int n = R.size(), m = S.size();
	for (int _ = 0; _ < n + m; _++) {
		int r1 = (r + 1) % n;
		int s1 = (s + 1) % m;
		Pos vr = R[r1] - R[r];
		Pos sr = S[s1] - S[s];
		Pos cur = H.back();
		assert(vr.Euc()); assert(sr.Euc());
		if (same_dir(vr, sr)) {
			if (vr.Euc() > sr.Euc()) return 0;
			r = (r + 1) % n;
			s = (s + 1) % m;
			if (vr.Euc() == sr.Euc()) continue;
			cur += sr - vr;
		}
		else {
			s = (s + 1) % m;
			cur += sr;
		}
		H.push_back(cur);
		if (H.back() == H[0]) break;
	}

	if (H.back() != H[0]) return 0;
	if (H.back() == H[0]) H.pop_back();
	S = graham_scan(H);
	return 1;
}
bool query() {
	std::cin >> N >> M;
	if (!N && !M) return 0;
	Polygon R(N), S(M);
	for (Pos& p : R) std::cin >> p;
	for (Pos& p : S) std::cin >> p;
	norm(R), norm(S);
	assert(convex(R));
	assert(convex(S));
	while (minkowski_difference(R, S));
	std::cout << area(R) + area(S) << "\n";
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	//freopen("../../../input_data/H_addition/H3", "r", stdin);
	//freopen("../../../input_data/H_addition/H_ret.txt", "w", stdout);
	while (query());
	return;
}
int main() { solve(); return 0; }//boj17584 Addition on Convex Polygons
accuracy: 1
time_ms: 1060
memory_kb: 3404
final_rank: 8

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::pair<int, int> pi;
typedef std::vector<int> Vint;
typedef std::vector<bool> Vbool;
typedef std::vector<ld> Vld;
const ll INF = 1e17;
const int LEN = 1e5 + 1;
const ld TOL = 1e-7;
const ll MOD = 1'000'000'007;
int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
bool zero(const ld& x) { return !sign(x); }
ll sq(int x) { return (ll)x * x; }
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }

int T, N, M;
struct Pos {
	int x, y, i;
	Pos(int X = 0, int Y = 0, int I = 0) : x(X), y(Y), i(I) {}
	bool operator == (const Pos& p) const { return x == p.x && y == p.y; }
	bool operator != (const Pos& p) const { return x != p.x || y != p.y; }
	//bool operator < (const Pos& p) const { return x == p.x ? y < p.y : x < p.x; }
	bool operator < (const Pos& p) const { return x == p.x ? y == p.y ? i > p.i : y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return x == p.x ? y <= p.y : x <= p.x; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const int& n) const { return { x * n, y * n }; }
	Pos operator / (const int& n) const { return { x / n, y / n }; }
	ll operator * (const Pos& p) const { return (ll)x * p.x + (ll)y * p.y; }
	ll operator / (const Pos& p) const { return (ll)x * p.y - (ll)y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const int& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const int& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ll xy() const { return (ll)x * y; }
	ll Euc() const { return (ll)x * x + (ll)y * y; }
	int Man() const { return std::abs(x) + std::abs(y); }
	ld mag() const { return hypot(x, y); }
	ld rad() const { return atan2(y, x); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return y > 0 || y == 0 && x >= 0; }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = Pos(0, 0);
typedef std::vector<Pos> Polygon;
ll cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ll cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
ll dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ll dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { ll ret = cross(d1, d2, d3); return ret < 0 ? -1 : !!ret; }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { ll ret = cross(d1, d2, d3, d4); return ret < 0 ? -1 : !!ret; }
bool same_dir(const Pos& p, const Pos& q) { return p * q >= 0 && p / q == 0; }
ll area(const Polygon& H) {
	ll ret = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) ret += H[i] / H[(i + 1) % sz];
	return ret;
}
void norm(Polygon& H) {
	ll A = area(H);
	if (A < 0) std::reverse(H.begin(), H.end());
	return;
}
void fit(Polygon& H) {
	auto p = std::min_element(H.begin(), H.end());
	std::rotate(H.begin(), p, H.end());
	return;
}
bool convex(Polygon& H) {
	int sz = H.size();
	for (int i = 0; i < sz; i++) {
		int i0 = (i - 1 + sz) % sz, i1 = i, i2 = (i + 1) % sz;
		if (ccw(H[i0], H[i1], H[i2]) <= 0) return 0;
	}
	return 1;
}
bool same_polygon(Polygon& R, Polygon& S) {
	fit(R); fit(S);
	int sz = R.size();
	if (sz != S.size()) return 0;
	Pos v = R[0] - S[0];
	for (Pos& p : S) p += v;
	for (int i = 0; i < sz; i++) if (R[i] != S[i]) return 0;
	return 1;
}
Polygon graham_scan(Polygon& C) {
	Polygon H;
	if (C.size() < 3) {
		std::sort(C.begin(), C.end());
		return C;
	}
	std::swap(C[0], *min_element(C.begin(), C.end()));
	std::sort(C.begin() + 1, C.end(), [&](const Pos& p, const Pos& q) -> bool {
		int ret = ccw(C[0], p, q);
		if (!ret) return (C[0] - p).Euc() < (C[0] - q).Euc();
		return ret > 0;
		}
	);
	C.erase(unique(C.begin(), C.end()), C.end());
	int sz = C.size();
	for (int i = 0; i < sz; i++) {
		while (H.size() >= 2 && ccw(H[H.size() - 2], H.back(), C[i]) <= 0)
			H.pop_back();
		H.push_back(C[i]);
	}
	return H;
}
bool minkovski_difference(Polygon& R, Polygon& S) {
	ll ar = area(R);
	ll as = area(S);
	if (ar == as) {
		if (same_polygon(R, S)) { S.clear(); return 0; }
		return 0;
	}
	if (ar > as) std::swap(R, S);
	if (R.size() > S.size()) return 0;
	int sz = R.size();
	Vbool F(sz, 0);
	Polygon V;
	for (int i = 0; i < sz; i++) {
		Pos v = R[(i + 1) % sz] - R[i];
		int gcd_ = gcd(std::abs(v.x), std::abs(v.y));
		v.x /= gcd_; v.y /= gcd_;
		v.i = i;
		V.push_back(v);
	}
	sz = S.size();
	for (int i = 0; i < sz; i++) {
		Pos v = S[(i + 1) % sz] - S[i];
		int gcd_ = gcd(std::abs(v.x), std::abs(v.y));
		v.x /= gcd_; v.y /= gcd_;
		v.i = ~i;
		V.push_back(v);
	}
	int r = -1, s = -1;
	std::sort(V.begin(), V.end());
	sz = V.size();
	for (int i = 0; i < sz - 1; i++) {
		if (V[i] == V[i + 1]) {
			assert(V[i].i >= 0); assert(V[i + 1].i < 0);
			if (!~r) r = V[i].i, s = ~V[i + 1].i;
			F[V[i].i] = 1;
		}
	}
	if (!~r) return 0;
	sz = F.size();
	for (int i = 0; i < sz; i++) if (!F[i]) return 0;

	Polygon H;
	H.push_back(Pos(0, 0));
	int n = R.size(), m = S.size();
	for (int _ = 0; _ < n + m; _++) {
		int r1 = (r + 1) % n;
		int s1 = (s + 1) % m;
		Pos vr = R[r1] - R[r];
		Pos sr = S[s1] - S[s];
		Pos cur = H.back();
		assert(vr.Euc()); assert(sr.Euc());
		if (same_dir(vr, sr)) {
			if (vr.Euc() > sr.Euc()) return 0;
			r = (r + 1) % n;
			s = (s + 1) % m;
			if (vr.Euc() == sr.Euc()) continue;
			cur += sr - vr;
		}
		else {
			s = (s + 1) % m;
			cur += sr;
		}
		H.push_back(cur);
		if (H.back() == H[0]) break;
	}

	if (H.back() != H[0]) return 0;
	if (H.back() == H[0]) H.pop_back();
	S = graham_scan(H);
	return 1;
}
bool query() {
	std::cin >> N >> M;
	if (!N && !M) return 0;
	Polygon R(N), S(M);
	for (Pos& p : R) std::cin >> p;
	for (Pos& p : S) std::cin >> p;
	norm(R), norm(S);
	assert(convex(R));
	assert(convex(S));
	while (minkovski_difference(R, S));
	std::cout << area(R) + area(S) << "\n";
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	//freopen("../../../input_data/H_addition/H3", "r", stdin);
	//freopen("../../../input_data/H_addition/H_ret.txt", "w", stdout);
	while (query());
	return;
}
int main() { solve(); return 0; }//boj17584 Addition on Convex Polygons
accuracy: 1
time_ms: 1060
memory_kb: 3408
final_rank: 9

code_snippet: #define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
#include <random>
#include <array>
#include <tuple>
typedef long long ll;
//typedef long double ld;
typedef double ld;
typedef std::pair<int, int> pi;
typedef std::vector<int> Vint;
typedef std::vector<bool> Vbool;
typedef std::vector<ld> Vld;
const ll INF = 1e17;
const int LEN = 1e5 + 1;
const ld TOL = 1e-7;
const ll MOD = 1'000'000'007;
int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
bool zero(const ld& x) { return !sign(x); }
ll sq(int x) { return (ll)x * x; }
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }

int T, N, M;
struct Pos {
	int x, y, i;
	Pos(int X = 0, int Y = 0, int I = 0) : x(X), y(Y), i(I) {}
	bool operator == (const Pos& p) const { return x == p.x && y == p.y; }
	bool operator != (const Pos& p) const { return x != p.x || y != p.y; }
	//bool operator < (const Pos& p) const { return x == p.x ? y < p.y : x < p.x; }
	bool operator < (const Pos& p) const { return x == p.x ? y == p.y ? i > p.i : y < p.y : x < p.x; }
	bool operator <= (const Pos& p) const { return x == p.x ? y <= p.y : x <= p.x; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const int& n) const { return { x * n, y * n }; }
	Pos operator / (const int& n) const { return { x / n, y / n }; }
	ll operator * (const Pos& p) const { return (ll)x * p.x + (ll)y * p.y; }
	ll operator / (const Pos& p) const { return (ll)x * p.y - (ll)y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const int& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const int& scale) { x /= scale; y /= scale; return *this; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	ll xy() const { return (ll)x * y; }
	ll Euc() const { return (ll)x * x + (ll)y * y; }
	int Man() const { return std::abs(x) + std::abs(y); }
	ld mag() const { return hypot(x, y); }
	ld rad() const { return atan2(y, x); }
	friend ld rad(const Pos& p1, const Pos& p2) { return atan2l(p1 / p2, p1 * p2); }
	int quad() const { return y > 0 || y == 0 && x >= 0; }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
}; const Pos O = Pos(0, 0);
typedef std::vector<Pos> Polygon;
ll cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
ll cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); }
ll dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); }
ll dot(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) * (d4 - d3); }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { ll ret = cross(d1, d2, d3); return ret < 0 ? -1 : !!ret; }
int ccw(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { ll ret = cross(d1, d2, d3, d4); return ret < 0 ? -1 : !!ret; }
bool same_dir(const Pos& p, const Pos& q) { return p * q >= 0 && p / q == 0; }
ll area(const Polygon& H) {
	ll ret = 0;
	int sz = H.size();
	for (int i = 0; i < sz; i++) ret += H[i] / H[(i + 1) % sz];
	return ret;
}
void norm(Polygon& H) {
	ll A = area(H);
	if (A < 0) std::reverse(H.begin(), H.end());
	return;
}
void fit(Polygon& H) {
	auto p = std::min_element(H.begin(), H.end());
	std::rotate(H.begin(), p, H.end());
	return;
}
bool convex(Polygon& H) {
	int sz = H.size();
	for (int i = 0; i < sz; i++) {
		int i0 = (i - 1 + sz) % sz, i1 = i, i2 = (i + 1) % sz;
		if (ccw(H[i0], H[i1], H[i2]) <= 0) return 0;
	}
	return 1;
}
bool same_polygon(Polygon& R, Polygon& S) {
	fit(R); fit(S);
	int sz = R.size();
	if (sz != S.size()) return 0;
	Pos v = R[0] - S[0];
	for (Pos& p : S) p += v;
	for (int i = 0; i < sz; i++) if (R[i] != S[i]) return 0;
	return 1;
}
Polygon graham_scan(Polygon& C) {
	Polygon H;
	if (C.size() < 3) {
		std::sort(C.begin(), C.end());
		return C;
	}
	std::swap(C[0], *min_element(C.begin(), C.end()));
	std::sort(C.begin() + 1, C.end(), [&](const Pos& p, const Pos& q) -> bool {
		int ret = ccw(C[0], p, q);
		if (!ret) return (C[0] - p).Euc() < (C[0] - q).Euc();
		return ret > 0;
		}
	);
	C.erase(unique(C.begin(), C.end()), C.end());
	int sz = C.size();
	for (int i = 0; i < sz; i++) {
		while (H.size() >= 2 && ccw(H[H.size() - 2], H.back(), C[i]) <= 0)
			H.pop_back();
		H.push_back(C[i]);
	}
	return H;
}
bool minkovski_difference(Polygon& R, Polygon& S) {
	if (same_polygon(R, S)) { S.clear(); return 0; }
	ll ar = area(R);
	ll as = area(S);
	if (ar == as) return 0;
	if (ar > as) std::swap(R, S);
	if (R.size() > S.size()) return 0;
	int sz = R.size();
	Vbool F(sz, 0);
	Polygon V;
	for (int i = 0; i < sz; i++) {
		Pos v = R[(i + 1) % sz] - R[i];
		int gcd_ = gcd(std::abs(v.x), std::abs(v.y));
		v.x /= gcd_; v.y /= gcd_;
		v.i = i;
		V.push_back(v);
	}
	sz = S.size();
	for (int i = 0; i < sz; i++) {
		Pos v = S[(i + 1) % sz] - S[i];
		int gcd_ = gcd(std::abs(v.x), std::abs(v.y));
		v.x /= gcd_; v.y /= gcd_;
		v.i = ~i;
		V.push_back(v);
	}
	int r = -1, s = -1;
	std::sort(V.begin(), V.end());
	sz = V.size();
	for (int i = 0; i < sz - 1; i++) {
		if (V[i] == V[i + 1]) {
			assert(V[i].i >= 0); assert(V[i + 1].i < 0);
			if (!~r) r = V[i].i, s = ~V[i + 1].i;
			F[V[i].i] = 1;
		}
	}
	if (!~r) return 0;
	sz = F.size();
	for (int i = 0; i < sz; i++) if (!F[i]) return 0;

	Polygon H;
	H.push_back(Pos(0, 0));
	int n = R.size(), m = S.size();
	for (int _ = 0; _ < n + m; _++) {
		int r1 = (r + 1) % n;
		int s1 = (s + 1) % m;
		Pos vr = R[r1] - R[r];
		Pos sr = S[s1] - S[s];
		Pos cur = H.back();
		assert(vr.Euc()); assert(sr.Euc());
		if (same_dir(vr, sr)) {
			if (vr.Euc() > sr.Euc()) return 0;
			r = (r + 1) % n;
			s = (s + 1) % m;
			if (vr.Euc() == sr.Euc()) continue;
			cur += sr - vr;
		}
		else {
			s = (s + 1) % m;
			cur += sr;
		}
		H.push_back(cur);
		if (H.back() == H[0]) break;
	}

	if (H.back() != H[0]) return 0;
	if (H.back() == H[0]) H.pop_back();
	S = graham_scan(H);
	//std::cout << "DEBUG:: " << area(R) << " " << area(S) << "\n";
	return 1;
}
bool query() {
	std::cin >> N >> M;
	if (!N && !M) return 0;
	Polygon R(N), S(M);
	for (Pos& p : R) std::cin >> p;
	for (Pos& p : S) std::cin >> p;
	norm(R), norm(S);
	assert(convex(R));
	assert(convex(S));
	//std::cout << "DEBUG:: " << area(R) << " " << area(S) << "\n";
	while (minkovski_difference(R, S));
	std::cout << area(R) + area(S) << "\n";
	return 1;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	//freopen("../../../input_data/H_addition/H3", "r", stdin);
	//freopen("../../../input_data/H_addition/H_ret.txt", "w", stdout);
	while (query());
	return;
}
int main() { solve(); return 0; }//boj17584 Addition on Convex Polygons
accuracy: 1
time_ms: 1080
memory_kb: 3496
final_rank: 10

code_snippet: #line 1 "library/my_template.hpp"
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using pi = pair<ll, ll>;
using vi = vector<ll>;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;

template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define FOR4_R(i, a, b, c) for (ll i = (b)-1; i >= ll(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) \
  overload4(__VA_ARGS__, FOR4_R, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define FOR_subset(t, s) for (ll t = s; t >= 0; t = (t == 0 ? -1 : (t - 1) & s))
#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll

template <typename T, typename U>
T SUM(const vector<U> &A) {
  T sum = 0;
  for (auto &&a: A) sum += a;
  return sum;
}

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T>
T pick(deque<T> &que) {
  T a = que.front();
  que.pop_front();
  return a;
}

template <typename T>
T pick(pq<T> &que) {
  T a = que.top();
  que.pop();
  return a;
}

template <typename T>
T pick(pqg<T> &que) {
  assert(que.size());
  T a = que.top();
  que.pop();
  return a;
}

template <typename T>
T pick(vc<T> &que) {
  assert(que.size());
  T a = que.back();
  que.pop_back();
  return a;
}

template <typename T, typename U>
T ceil(T x, U y) {
  return (x > 0 ? (x + y - 1) / y : x / y);
}

template <typename T, typename U>
T floor(T x, U y) {
  return (x > 0 ? x / y : (x - y + 1) / y);
}

template <typename T, typename U>
pair<T, T> divmod(T x, U y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

template <typename F>
ll binary_search(F check, ll ok, ll ng) {
  assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
  }
  return ok;
}

template <typename F>
double binary_search_real(F check, double ok, double ng, int iter = 100) {
  FOR(iter) {
    double x = (ok + ng) / 2;
    tie(ok, ng) = (check(x) ? mp(x, ng) : mp(ok, x));
  }
  return (ok + ng) / 2;
}

template <class T, class S>
inline bool chmax(T &a, const S &b) {
  return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
  return (a > b ? a = b, 1 : 0);
}

vc<int> s_to_vi(const string &S, char first_char) {
  vc<int> A(S.size());
  FOR(i, S.size()) { A[i] = S[i] - first_char; }
  return A;
}

template <typename T, typename U>
vector<T> cumsum(vector<U> &A, int off = 1) {
  int N = A.size();
  vector<T> B(N + 1);
  FOR(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

template <typename CNT, typename T>
vc<CNT> bincount(const vc<T> &A, int size) {
  vc<CNT> C(size);
  for (auto &&x: A) { ++C[x]; }
  return C;
}

// stable
template <typename T>
vector<int> argsort(const vector<T> &A) {
  vector<int> ids(A.size());
  iota(all(ids), 0);
  sort(all(ids),
       [&](int i, int j) { return A[i] < A[j] || (A[i] == A[j] && i < j); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
  int n = len(I);
  vc<T> B(n);
  FOR(i, n) B[i] = A[I[i]];
  return B;
}
#line 1 "library/other/io2.hpp"
#define INT(...) \
  int __VA_ARGS__; \
  IN(__VA_ARGS__)
#define LL(...) \
  ll __VA_ARGS__; \
  IN(__VA_ARGS__)
#define STR(...) \
  string __VA_ARGS__; \
  IN(__VA_ARGS__)
#define CHR(...) \
  char __VA_ARGS__; \
  IN(__VA_ARGS__)
#define DBL(...) \
  long double __VA_ARGS__; \
  IN(__VA_ARGS__)

#define VEC(type, name, size) \
  vector<type> name(size);    \
  read(name)
#define VV(type, name, h, w)                     \
  vector<vector<type>> name(h, vector<type>(w)); \
  read(name)

void read(int &a) { cin >> a; }
void read(long long &a) { cin >> a; }
void read(char &a) { cin >> a; }
void read(double &a) { cin >> a; }
void read(long double &a) { cin >> a; }
void read(string &a) { cin >> a; }
template <class T, class S> void read(pair<T, S> &p) { read(p.first), read(p.second); }
template <class T> void read(vector<T> &a) {for(auto &i : a) read(i);}
template <class T> void read(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
  read(head);
  IN(tail...);
}

template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& A) {
  os << A.fi << " " << A.se;
  return os;
}

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

void print() {
  cout << "\n";
  cout.flush();
}

template <class Head, class... Tail>
void print(Head&& head, Tail&&... tail) {
  cout << head;
  if (sizeof...(Tail)) cout << " ";
  print(forward<Tail>(tail)...);
}

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
#line 2 "library/geo/base.hpp"
template <typename T>
struct Point {
  T x, y;

  Point() = default;

  template <typename A, typename B>
  Point(A x, B y) : x(x), y(y) {}

  template <typename A, typename B>
  Point(pair<A, B> p) : x(p.fi), y(p.se) {}

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

  bool operator<(Point p) const {
    if (x != p.x) return x < p.x;
    return y < p.y;
  }

  T dot(Point other) { return x * other.x + y * other.y; }
  T det(Point other) { return x * other.y - y * other.x; }
};

template <typename REAL, typename T>
REAL dist(Point<T> A, Point<T> B) {
  A -= B;
  T p = A.dot(A);
  return sqrt(REAL(p));
}

template <typename T>
struct Line {
  T a, b, c;

  Line(T a, T b, T c) : a(a), b(b), c(c) {}
  Line(Point<T> A, Point<T> B) {
    a = A.y - B.y;
    b = B.x - A.x;
    c = A.x * B.y - A.y * B.x;
  }
  Line(T x1, T y1, T x2, T y2) : Line(Point<T>(x1, y1), Point<T>(x2, y2)) {}

  template <typename U>
  U eval(Point<U> P) {
    return a * P.x + b * P.y + c;
  }

  template <typename U>
  T eval(U x, U y) {
    return a * x + b * y + c;
  }

  bool is_parallel(Line other) { return a * other.b - b * other.a == 0; }

  bool is_orthogonal(Line other) { return a * other.a + b * other.b == 0; }
};

template <typename T>
struct Segment {
  Point<T> A, B;

  Segment(Point<T> A, Point<T> B) : A(A), B(B) {}
  Segment(T x1, T y1, T x2, T y2)
      : Segment(Point<T>(x1, y1), Point<T>(x2, y2)) {}

  Line<T> to_Line() { return Line(A, B); }
};

template <typename T>
struct Circle {
  Point<T> O;
  T r;
  Circle(Point<T> O, T r) : O(O), r(r) {}
  Circle(T x, T y, T r) : O(Point<T>(x, y)), r(r) {}
};

template <typename T>
struct Polygon {
  vc<Point<T>> points;
  T a;

  template <typename A, typename B>
  Polygon(vc<pair<A, B>> pairs) {
    for (auto&& [a, b]: pairs) points.eb(Point<T>(a, b));
    build();
  }
  Polygon(vc<Point<T>> points) : points(points) { build(); }

  int size() { return len(points); }

  template <typename REAL>
  REAL area() {
    return a * 0.5;
  }

  template <enable_if_t<is_integral<T>::value, int> = 0>
  T area_2() {
    return a;
  }

  bool is_convex() {
    FOR(j, len(points)) {
      int i = (j == 0 ? len(points) - 1 : j - 1);
      int k = (j == len(points) - 1 ? 0 : j + 1);
      if ((points[j] - points[i]).det(points[k] - points[j]) < 0) return false;
    }
    return true;
  }

private:
  void build() {
    a = 0;
    FOR(i, len(points)) {
      int j = (i + 1 == len(points) ? 0 : i + 1);
      a += points[i].det(points[j]);
    }
    if (a < 0) {
      a = -a;
      reverse(all(points));
    }
  }
};
#line 2 "library/geo/angle_sort.hpp"

// 偏角ソートに対する argsort
template <typename T>
vector<int> angle_argsort(vector<Point<T>>& P) {
  vector<int> lower, origin, upper;
  const Point<T> O = {0, 0};
  FOR(i, len(P)) {
    if (P[i] == O) origin.eb(i);
    elif ((P[i].y < 0) || (P[i].y == 0 && P[i].x > 0)) lower.eb(i);
    else upper.eb(i);
  }
  sort(all(lower), [&](auto& i, auto& j) { return P[i].det(P[j]) > 0; });
  sort(all(upper), [&](auto& i, auto& j) { return P[i].det(P[j]) > 0; });
  auto& I = lower;
  I.insert(I.end(), all(origin));
  I.insert(I.end(), all(upper));
  return I;
}

// 偏角ソートに対する argsort
template <typename T>
vector<int> angle_argsort(vector<pair<T, T>>& P) {
  vc<Point<T>> tmp(len(P));
  FOR(i, len(P)) tmp[i] = Point<T>(P[i]);
  return angle_argsort<T>(tmp);
}

// inplace に偏角ソートする
// index が欲しい場合は angle_argsort
template <typename T>
void angle_sort(vector<Point<T>>& P) {
  auto I = angle_argsort<T>(P);
  P = rearrange(P, I);
}

// inplace に偏角ソートする
// index が欲しい場合は angle_argsort
template <typename T>
void angle_sort(vector<pair<T, T>>& P) {
  auto I = angle_argsort<T>(P);
  P = rearrange(P, I);
}
#line 4 "main.cpp"

void solve() {
  ll N, M;
  while (cin >> N >> M) {
    if (N == 0 && M == 0) break;
    VEC(pi, AB, N);
    VEC(pi, CD, M);
    AB.eb(AB[0]);
    CD.eb(CD[0]);

    map<pi, pi> CNT;
    FOR(i, N) {
      auto [a1, b1] = AB[i];
      auto [a2, b2] = AB[i + 1];
      ll a = a2 - a1, b = b2 - b1;
      ll g = gcd(a, b);
      pi v = {a / g, b / g};
      // ベクトル v が g 個
      CNT[v].fi += g;
    }
    FOR(i, M) {
      auto [a1, b1] = CD[i];
      auto [a2, b2] = CD[i + 1];
      ll a = a2 - a1, b = b2 - b1;
      ll g = gcd(a, b);
      pi v = {a / g, b / g};
      // ベクトル v が g 個
      CNT[v].se += g;
    }
    vc<pi> vecs;
    vi P, Q;
    for (auto&& [v, pq]: CNT) {
      vecs.eb(v);
      auto [p, q] = pq;
      P.eb(p);
      Q.eb(q);
    }
    auto I = angle_argsort(vecs);
    vecs = rearrange(vecs, I);
    P = rearrange(P, I);
    Q = rearrange(Q, I);

    while (1) {
      bool upd = 0;
      FOR(2) {
        swap(P, Q);
        const ll INF = 1LL << 60;
        ll k = INF;
        FOR(i, len(vecs)) {
          if (Q[i] == 0) continue;
          chmin(k, P[i] / Q[i]);
        }
        if (k > 0 && k < INF) upd = 1;
        FOR(i, len(vecs)) { P[i] -= k * Q[i]; }
      }
      if (!upd) break;
    }

    auto calc = [&](vi A) -> ll {
      ll area = 0;
      ll x = 0, y = 0;
      FOR(i, len(vecs)) {
        auto [dx, dy] = vecs[i];
        dx *= A[i];
        dy *= A[i];
        ll x1 = x + dx, y1 = y + dy;
        area += x * y1 - y * x1;
        x = x1, y = y1;
      }
      return area;
    };
    ll ANS = calc(P) + calc(Q);
    print(ANS);
  }
}

signed main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << setprecision(15);

  solve();

  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3592
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i, n) for(ll i = 0; i < (n); i++)
using P = vector<pair<ll, ll>>;

constexpr int type(ll x, ll y) {
    if(x == 0 and y == 0) return 0;
    if(y < 0 or (y == 0 and x > 0)) return -1;
    return 1;
}

bool arg_cmp(pair<ll, ll> x, pair<ll, ll> y) {
    int L = type(x.first, x.second), R = type(y.first, y.second);
    if(L != R) return L < R;
    ll X = x.first * y.second, Y = y.first * x.second;
    if(X != Y) return X > Y;
    return x.first < y.first;
}

long long solve(P &x, P &y, int second = 0) {
    bool flag = true;
    int j = 0;
    P ny;
    if(empty(x)) flag = false;
    for(auto &[a, b] : x) {
        while(j < y.size()) {
            auto &[c, d] = y[j];
            if(a * d == b * c and abs(a + b) <= abs(c + d)) { break; }
            ny.emplace_back(c, d);
            j++;
        }
        if(j == y.size()) {
            flag = false;
            break;
        }
        if(y[j].first - a or y[j].second - b) ny.emplace_back(y[j].first - a, y[j].second - b);
        j++;
    }
    while(j < y.size()) { ny.emplace_back(y[j++]); }
    if(flag)
        return solve(x, ny);
    else if(!second) { return solve(y, x, true); }

    ll res = 0;
    auto calc = [&](const P &x) {
        pair<ll, ll> p{};
        rep(i, x.size()) {
            pair<ll, ll> np(p.first + x[i].first, p.second + x[i].second);
            res += p.first * np.second - p.second * np.first;
            p = np;
        }
    };
    calc(x);
    calc(y);
    return res;
}

signed main() {
    while(true) {
        int n, m;
        cin >> n >> m;
        if(!n) exit(0);
        auto get = [](int n) {
            P r(n);
            rep(i, n) cin >> r[i].first >> r[i].second;
            P res(n);
            rep(i, n) res[i] = pair(r[(i + 1) % n].first - r[i].first, r[(i + 1) % n].second - r[i].second);

            int k = min_element(begin(res), end(res), arg_cmp) - begin(res);
            rotate(begin(res), begin(res) + k, end(res));
            return pair(r, res);
        };
        auto [r, x] = get(n);
        auto [s, y] = get(m);

        ll res = solve(x, y);
        cout << res << endl;
    }
}
accuracy: 1
time_ms: 210
memory_kb: 143856
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, n) for(int i = 0; i < (n); i++)
#define ll long long
using P = vector<pair<ll, ll>>;

constexpr int type(ll x, ll y) {
    if(x == 0 and y == 0) return 0;
    if(y < 0 or (y == 0 and x > 0)) return -1;
    return 1;
}

bool arg_cmp(pair<ll, ll> x, pair<ll, ll> y) {
    int L = type(x.first, x.second), R = type(y.first, y.second);
    if(L != R) return L < R;
    long long X = x.first * y.second, Y = y.first * x.second;
    if(X != Y) return X > Y;
    return x.first < y.first;
}

long long solve(P &x, P &y, int second = 0) {
    bool flag = true;
    int j = 0;
    P ny;
    if(empty(x)) flag = false;
    for(auto &[a, b] : x) {
        while(j < y.size()) {
            auto &[c, d] = y[j];
            if(a * d == b * c and abs(a + b) <= abs(c + d)) { break; }
            ny.emplace_back(c, d);
            j++;
        }
        if(j == y.size()) {
            flag = false;
            break;
        }
        if(y[j].first - a or y[j].second - b) ny.emplace_back(y[j].first - a, y[j].second - b);
        j++;
    }
    while(j < y.size()) { ny.emplace_back(y[j++]); }
    if(flag)
        return solve(x, ny);
    else if(!second) { return solve(y, x, true); }

    ll res = 0;
    auto calc = [&](const P &x) {
        pair<ll, ll> p{};
        rep(i, x.size()) {
            pair<ll, ll> np(p.first + x[i].first, p.second + x[i].second);
            res += p.first * np.second - p.second * np.first;
            p = np;
        }
    };
    calc(x);
    calc(y);
    return res;
}

signed main() {
    while(true) {
        int n, m;
        cin >> n >> m;
        if(!n) exit(0);
        auto get = [](int n) {
            P r(n);
            rep(i, n) cin >> r[i].first >> r[i].second;
            P res(n);
            rep(i, n) res[i] = pair(r[(i + 1) % n].first - r[i].first, r[(i + 1) % n].second - r[i].second);

            int k = min_element(begin(res), end(res), arg_cmp) - begin(res);
            rotate(begin(res), begin(res) + k, end(res));
            return pair(r, res);
        };
        auto [r, x] = get(n);
        auto [s, y] = get(m);

        int res = solve(x, y);
        cout << res << endl;
    }
}
accuracy: 1
time_ms: 210
memory_kb: 143744
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, n) for(int i = 0; i < (n); i++)
using P = vector<pair<int, int>>;

constexpr int type(int x, int y) {
    if(x == 0 and y == 0) return 0;
    if(y < 0 or (y == 0 and x > 0)) return -1;
    return 1;
}

bool arg_cmp(pair<int, int> x, pair<int, int> y) {
    int L = type(x.first, x.second), R = type(y.first, y.second);
    if(L != R) return L < R;
    long long X = 1LL * x.first * y.second, Y = 1LL * y.first * x.second;
    if(X != Y) return X > Y;
    return x.first < y.first;
}

long long solve(P &x, P &y, int second = 0) {
    bool flag = true;
    int j = 0;
    P ny;
    if(empty(x)) flag = false;
    for(auto &[a, b] : x) {
        while(j < y.size()) {
            auto &[c, d] = y[j];
            if(1LL * a * d == 1LL * b * c and abs(a + b) <= abs(c + d)) { break; }
            ny.emplace_back(c, d);
            j++;
        }
        if(j == y.size()) {
            flag = false;
            break;
        }
        if(y[j].first - a or y[j].second - b) ny.emplace_back(y[j].first - a, y[j].second - b);
        j++;
    }
    while(j < y.size()) { ny.emplace_back(y[j++]); }
    if(flag)
        return solve(x, ny);
    else if(!second) { return solve(y, x, true); }

    long long res = 0;
    auto calc = [&](const P &x) {
        pair<int, int> p{};
        rep(i, x.size()) {
            pair<int, int> np(p.first + x[i].first, p.second + x[i].second);
            res += 1LL * p.first * np.second - 1LL * p.second * np.first;
            p = np;
        }
    };
    calc(x);
    calc(y);
    return res;
}

signed main() {
    while(true) {
        int n, m;
        cin >> n >> m;
        if(!n) exit(0);
        auto get = [](int n) {
            P r(n);
            rep(i, n) cin >> r[i].first >> r[i].second;
            P res(n);
            rep(i, n) res[i] = pair(r[(i + 1) % n].first - r[i].first, r[(i + 1) % n].second - r[i].second);

            int k = min_element(begin(res), end(res), arg_cmp) - begin(res);
            rotate(begin(res), begin(res) + k, end(res));
            return pair(r, res);
        };
        auto [r, x] = get(n);
        auto [s, y] = get(m);

        int res = solve(x, y);
        cout << res << endl;
    }
}
accuracy: 1
time_ms: 200
memory_kb: 143484
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, n) for(int i = 0; i < (n); i++)
using P = vector<pair<int, int>>;

constexpr int type(int x, int y) {
    if(x == 0 and y == 0) return 0;
    if(y < 0 or (y == 0 and x > 0)) return -1;
    return 1;
}

bool arg_cmp(pair<int, int> x, pair<int, int> y) {
    int L = type(x.first, x.second), R = type(y.first, y.second);
    if(L != R) return L < R;
    long long X = 1LL * x.first * y.second, Y = 1LL * y.first * x.second;
    if(X != Y) return X > Y;
    return x.first < y.first;
}

long long solve(P &x, P &y, int second = 0) {
    bool flag = true;
    int j = 0;
    P ny;
    if(empty(x)) flag = false;
    for(auto &[a, b] : x) {
        while(j < y.size()) {
            auto &[c, d] = y[j];
            if(1LL * a * d == 1LL * b * c and abs(a + b) <= abs(c + d)) { break; }
            ny.emplace_back(c, d);
            j++;
        }
        if(j == y.size()) {
            flag = false;
            break;
        }
        if(y[j].first - a or y[j].second - b) ny.emplace_back(y[j].first - a, y[j].second - b);
        j++;
    }
    while(j < y.size()) { ny.emplace_back(y[j++]); }
    if(flag)
        return solve(x, ny);
    else if(!second) { return solve(y, x, true); }

    long long res = 0;
    auto calc = [&](const P &x) {
        pair<int, int> p{};
        rep(i, x.size()) {
            pair<int, int> np(p.first + x[i].first, p.second + x[i].second);
            res += 1LL * p.first * np.second - 1LL * p.second * np.first;
            p = np;
        }
    };
    calc(x);
    calc(y);
    return res;
}

signed main() {
    while(true) {
        int n, m;
        cin >> n >> m;
        if(!n) exit(0);
        auto get = [](int n) {
            P r(n);
            rep(i, n) cin >> r[i].first >> r[i].second;
            P res(n);
            rep(i, n) res[i] = pair(r[(i + 1) % n].first - r[i].first, r[(i + 1) % n].second - r[i].second);

            int k = min_element(begin(res), end(res), arg_cmp) - begin(res);
            rotate(begin(res), begin(res) + k, end(res));
            return pair(r, res);
        };
        auto [r, x] = get(n);
        auto [s, y] = get(m);

        int res = solve(x, y);
        cout << res << endl;
        if(res == 3520194) {
            cout << n << endl;
            rep(i, n) cout << r[i].first << " " << r[i].second << endl;
            cout << m << endl;
            rep(i, m) cout << s[i].first << " " << s[i].second << endl;
        }
    }
}
accuracy: 1
time_ms: 200
memory_kb: 143480
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,n) for(int i=1;i<=int(n);i++)
#define per(i,n) for(int i=int(n)-1;i>=0;i--)
#define per1(i,n) for(int i=int(n);i>0;i--)
#define all(c) c.begin(),c.end()
#define si(x) int(x.size())
#define pb push_back
#define eb emplace_back
#define fs first
#define sc second
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
template<class T,class U> bool chmax(T& x, U y){
	if(x<y){ x=y; return true; }
	return false;
}
template<class T,class U> bool chmin(T& x, U y){
	if(y<x){ x=y; return true; }
	return false;
}
template<class T> void mkuni(V<T>& v){sort(all(v));v.erase(unique(all(v)),v.end());}
template<class T> int lwb(const V<T>& v, const T& a){return lower_bound(all(v),a) - v.begin();}
template<class T>
V<T> Vec(size_t a) {
    return V<T>(a);
}
template<class T, class... Ts>
auto Vec(size_t a, Ts... ts) {
  return V<decltype(Vec<T>(ts...))>(a, Vec<T>(ts...));
}
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }

#ifdef LOCAL
#define show(x) cerr << "LINE" << __LINE__ << " : " << #x << " = " << (x) << endl
void dmpr(ostream& os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ~ ";
	dmpr(os,args...);
}
#define shows(...) cerr << "LINE" << __LINE__ << " : ";dmpr(cerr,##__VA_ARGS__)
#define dump(x) cerr << "LINE" << __LINE__ << " : " << #x << " = {";  \
	for(auto v: x) cerr << v << ","; cerr << "}" << endl;
#else
#define show(x) void(0)
#define dump(x) void(0)
#define shows(...) void(0)
#endif

template<class D> D divFloor(D a, D b){
	return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
template<class D> D divCeil(D a, D b) {
	return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}

using P = pair<ll,ll>;
P operator+(P a,P b){return P(a.fs+b.fs,a.sc+b.sc);}
P operator-(P a,P b){return P(a.fs-b.fs,a.sc-b.sc);}
P operator*(P a,ll k){return P(a.fs*k,a.sc*k);}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);		//DON'T USE scanf/printf/puts !!
	cout << fixed << setprecision(20);

	auto comp = [&](P l,P r){
		auto sho = [&](P p){
			ll x=p.fs,y=p.sc;
			if(x>0&&y>=0) return 0;
			if(x<=0&&y>0) return 1;
			if(x<0&&y<=0) return 2;
			if(x>=0&&y<0) return 3;
			assert(false);
		};
		int s = sho(l), t = sho(r);
		if(s != t) return s<t;
		return l.sc*r.fs < l.fs*r.sc;
	};


	while(true){
		int A,B; cin >> A >> B;
		if(A == 0) break;
		V<P> vec;
		V<ll> a,b;
		{
			V<P> aa(A),bb(B);

			V<P> f(A);
			rep(i,A) cin >> f[i].fs >> f[i].sc;
			f.pb(f[0]);
			rep(i,A) aa[i] = f[i+1]-f[i];
			f = V<P>(B);
			rep(i,B) cin >> f[i].fs >> f[i].sc;
			f.pb(f[0]);
			rep(i,B) bb[i] = f[i+1]-f[i];

			for(P p: aa){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				vec.pb(v);
			}
			for(P p: bb){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				vec.pb(v);
			}
			mkuni(vec);
			sort(all(vec),comp);
			int K = si(vec);
			a = V<ll>(K), b = V<ll>(K);
			for(P p: aa){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				a[lower_bound(all(vec),v,comp) - vec.begin()] = g;
			}
			for(P p: bb){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				b[lower_bound(all(vec),v,comp) - vec.begin()] = g;
			}
		}
		show(vec);show(a);show(b);
		int N = si(a);
		while(true){
			if(accumulate(all(a),0LL) < accumulate(all(b),0LL)) swap(a,b);
			if(accumulate(all(b),0LL) == 0) break;
			ll k = TEN(18);
			rep(i,N) if(b[i]) chmin(k,a[i]/b[i]);
			if(k == 0) break;
			rep(i,N) a[i] -= k*b[i];
		}
		show(a);show(b);
		ll ans = 0;
		for(const auto f: {a,b}){
			V<P> p(N);
			rep(i,N-1) p[i+1] = p[i] + vec[i] * f[i];
			p.pb(p[0]);
			rep(i,N) ans += p[i+1].sc*p[i].fs-p[i].sc*p[i+1].fs;
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3548
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,n) for(int i=1;i<=int(n);i++)
#define per(i,n) for(int i=int(n)-1;i>=0;i--)
#define per1(i,n) for(int i=int(n);i>0;i--)
#define all(c) c.begin(),c.end()
#define si(x) int(x.size())
#define pb push_back
#define eb emplace_back
#define fs first
#define sc second
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
template<class T,class U> bool chmax(T& x, U y){
	if(x<y){ x=y; return true; }
	return false;
}
template<class T,class U> bool chmin(T& x, U y){
	if(y<x){ x=y; return true; }
	return false;
}
template<class T> void mkuni(V<T>& v){sort(all(v));v.erase(unique(all(v)),v.end());}
template<class T> int lwb(const V<T>& v, const T& a){return lower_bound(all(v),a) - v.begin();}
template<class T>
V<T> Vec(size_t a) {
    return V<T>(a);
}
template<class T, class... Ts>
auto Vec(size_t a, Ts... ts) {
  return V<decltype(Vec<T>(ts...))>(a, Vec<T>(ts...));
}
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }

#ifdef LOCAL
#define show(x) cerr << "LINE" << __LINE__ << " : " << #x << " = " << (x) << endl
void dmpr(ostream& os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ~ ";
	dmpr(os,args...);
}
#define shows(...) cerr << "LINE" << __LINE__ << " : ";dmpr(cerr,##__VA_ARGS__)
#define dump(x) cerr << "LINE" << __LINE__ << " : " << #x << " = {";  \
	for(auto v: x) cerr << v << ","; cerr << "}" << endl;
#else
#define show(x) void(0)
#define dump(x) void(0)
#define shows(...) void(0)
#endif

template<class D> D divFloor(D a, D b){
	return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
template<class D> D divCeil(D a, D b) {
	return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}

using P = pair<ll,ll>;
P operator+(P a,P b){return P(a.fs+b.fs,a.sc+b.sc);}
P operator-(P a,P b){return P(a.fs-b.fs,a.sc-b.sc);}
P operator*(P a,ll k){return P(a.fs*k,a.sc*k);}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);		//DON'T USE scanf/printf/puts !!
	cout << fixed << setprecision(20);

	auto comp = [&](P l,P r){
		auto sho = [&](P p){
			ll x=p.fs,y=p.sc;
			if(x>0&&y>=0) return 0;
			if(x<=0&&y>0) return 1;
			if(x<0&&y<=0) return 2;
			if(x>=0&&y<0) return 3;
			assert(false);
		};
		int s = sho(l), t = sho(r);
		if(s != t) return s<t;
		return l.sc*r.fs < l.fs*r.sc;
	};


	while(true){
		int A,B; cin >> A >> B;
		if(A == 0) break;
		V<P> vec;
		V<ll> a,b;
		{
			V<P> aa(A),bb(B);

			V<P> f(A);
			rep(i,A) cin >> f[i].fs >> f[i].sc;
			f.pb(f[0]);
			rep(i,A) aa[i] = f[i+1]-f[i];
			f = V<P>(B);
			rep(i,B) cin >> f[i].fs >> f[i].sc;
			f.pb(f[0]);
			rep(i,B) bb[i] = f[i+1]-f[i];

			for(P p: aa){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				vec.pb(v);
			}
			for(P p: bb){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				vec.pb(v);
			}
			mkuni(vec);
			sort(all(vec),comp);
			int K = si(vec);
			a = V<ll>(K), b = V<ll>(K);
			for(P p: aa){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				a[lower_bound(all(vec),v,comp) - vec.begin()] = g;
			}
			for(P p: bb){
				ll g = __gcd(p.fs,p.sc); g = abs(g);
				P v(p.fs/g, p.sc/g);
				b[lower_bound(all(vec),v,comp) - vec.begin()] = g;
			}
		}
		show(vec);show(a);show(b);
		int N = si(a);
		while(true){
			if(accumulate(all(a),0LL) < accumulate(all(b),0LL)) swap(a,b);
			if(accumulate(all(b),0LL) == 0) break;
			ll k = TEN(18);
			rep(i,N) if(b[i]) chmin(k,a[i]/b[i]);
			if(k == 0) break;
			rep(i,N) a[i] -= k*b[i];
		}
		show(a);show(b);
		ll ans = 0;
		for(const auto f: {a,b}){
			V<P> p(N);
			rep(i,N-1) p[i+1] = p[i] + vec[i] * f[i];
			p.pb(p[0]);
			rep(i,N) ans += p[i+1].sc*p[i].fs-p[i].sc*p[i+1].fs;
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3544
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
using namespace std;

typedef long long LL;
typedef pair<LL,LL> pll;

pll add(const pll &a, const pll &b){
	return pll(a.first + b.first, a.second + b.second);
}

pll sub(const pll &a, const pll &b){
	return pll(a.first - b.first, a.second - b.second);
}

pll mul(LL t, const pll &a){
	return pll(a.first * t, a.second * t);
}

LL cross(const pll &a, const pll &b){
	return a.first * b.second - b.first * a.second;
}

LL div(const pll &a, const pll &b){
	if(b.first != 0){ return a.first / b.first; }
	return a.second / b.second;
}

vector<pll> input(int n){
	vector<pll> pts(n);
	for(int i = 0; i < n; ++i){
		cin >> pts[i].first >> pts[i].second;
	}
	rotate(pts.begin(), min_element(pts.begin(), pts.end()), pts.end());

	vector<pll> vec(n);
	for(int i = 0; i < n; ++i){
		vec[i] = sub(pts[i + 1], pts[i]);
	}
	vec[n - 1] = sub(pts[0], pts[n - 1]);
	return vec;
}

LL area(const vector<pll> &v){
	int n = v.size();
	pll p;
	LL s = 0;
	for(int i = 0; i < n; ++i){
		pll q = add(p, v[i]);
		s += cross(p, q);
		p = q;
	}
	return s;
}

int main(){
	int n, m;
	while(cin >> n >> m && n){
		vector<pll> v1 = input(n);
		vector<pll> v2 = input(m);
		if(area(v1) > area(v2)){ v1.swap(v2); }
		vector<int> idxs;
		while(true){
			int s1 = v1.size(), s2 = v2.size();
			idxs.assign(s1, -1);
			int j = 0;
			LL u = 1LL << 50;
			for(int i = 0; i < s1; ++i){
				for(; j < s2; ++j){
					if(cross(v1[i], v2[j]) == 0){ break; }
				}
				if(j >= s2){
					u = 0;
					break;
				}
				idxs[i] = j;
				LL t = div(v2[j], v1[i]);
				u = min(t, u);
				++j;
			}
			if(u <= 0){ break; }
			for(int i = 0; i < s1; ++i){
				int k = idxs[i];
				v2[k] = sub(v2[k], mul(u, v1[i]));
			}
			v2.erase(remove(v2.begin(), v2.end(), pll()), v2.end());
			v1.swap(v2);
		}
		LL a1 = area(v1);
		LL a2 = area(v2);
		cout << (a1 + a2) << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3168
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;

typedef long long LL;
typedef pair<LL,LL> pll;

pll add(const pll &a, const pll &b){
	return pll(a.first + b.first, a.second + b.second);
}

pll sub(const pll &a, const pll &b){
	return pll(a.first - b.first, a.second - b.second);
}

pll mul(LL t, const pll &a){
	return pll(a.first * t, a.second * t);
}

LL cross(const pll &a, const pll &b){
	return a.first * b.second - b.first * a.second;
}

LL div(const pll &a, const pll &b){
	if(b.first != 0){ return a.first / b.first; }
	return a.second / b.second;
}

vector<pll> input(int n){
	vector<pll> pts(n);
	for(int i = 0; i < n; ++i){
		cin >> pts[i].first >> pts[i].second;
	}
	rotate(pts.begin(), min_element(pts.begin(), pts.end()), pts.end());

	vector<pll> vec(n);
	for(int i = 0; i < n; ++i){
		vec[i] = sub(pts[i + 1], pts[i]);
	}
	vec[n - 1] = sub(pts[0], pts[n - 1]);
	return vec;
}

LL area(const vector<pll> &v){
	int n = v.size();
	pll p;
	LL s = 0;
	for(int i = 0; i < n; ++i){
		pll q = add(p, v[i]);
		s += cross(p, q);
		p = q;
	}
	return s;
}

int main(){
	int n, m;
	while(cin >> n >> m && n){
		vector<pll> v1 = input(n);
		vector<pll> v2 = input(m);
		if(area(v1) > area(v2)){ v1.swap(v2); }
		vector<int> idxs;
		while(true){
			int s1 = v1.size(), s2 = v2.size();
			idxs.assign(s1, -1);
			int j = 0;
			LL u = 1LL << 50;
			for(int i = 0; i < s1; ++i){
				for(; j < s2; ++j){
					if(cross(v1[i], v2[j]) == 0){ break; }
				}
				if(j >= s2){
					u = 0;
					break;
				}
				idxs[i] = j;
				LL t = div(v2[j], v1[i]);
				u = min(t, u);
				++j;
			}
			if(u <= 0){ break; }
			for(int i = 0; i < s1; ++i){
				int k = idxs[i];
				v2[k] = sub(v2[k], mul(u, v1[i]));
			}
			v2.erase(remove(v2.begin(), v2.end(), pll()), v2.end());
			v1.swap(v2);
		}
		LL a1 = area(v1);
		LL a2 = area(v2);
		cout << (a1 + a2) << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3148
final_rank: 1