#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;

ll ox, oy;

struct point {
	ll x, y;
	bool blue;
	point() : x(0), y(0), blue(0) {}
	point(const ll x, const ll y) : x(x), y(y) {}

	bool operator < ( const point & Q ) const {
		if (x != Q.x) return x < Q.x;
		return y < Q.y;
	}

	friend ostream & operator << ( ostream & cout, point & Q ) {
		return cout << '[' << Q.x << ", " << Q.y << ']';
	}
} A[500], B[500], C[500], D[500];

inline bool compare( const point & P, const point & Q ) {
	point A( P.x - ox, P.y - oy ), B( Q.x - ox, Q.y - oy );
	if ( A.x * B.y == A.y * B.x ) return P.blue > Q.blue;
	else return A.x * B.y > A.y * B.x;
	//return A.x * B.y > A.y * B.x;
}

int main() {
	//freopen("napredna.in", "r", stdin);
	int n, m, num = 0;
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) scanf("%I64d%I64d", &A[i].x, &A[i].y);
	for (int i = 0; i < m; i++) {
		scanf("%I64d%I64d", &B[i].x, &B[i].y);
		B[i].blue = 1;
	}
	sort( A, A + n );
	sort( B, B + m );
	for (int i = 0, zomg = 0; i < n - 2; i++) {
		while ( zomg < m && B[zomg] < A[i] ) zomg++;
		memcpy( C + i + 1, A + i + 1, sizeof(point) * (n - i - 1) );
		memcpy( D + zomg, B + zomg, sizeof(point) * (m - zomg) );
		ox = A[i].x;
		oy = A[i].y;
		sort( C + i + 1, C + n, compare );
		sort( D + zomg, D + m, compare );

		for (int j = i + 1; j < n - 1; j++) {
			ll VX = C[j].x - A[i].x;
			ll VY = C[j].y - A[i].y;

			int k1 = j + 1;
			int k2 = zomg;
			cout << k1 << ' ' << k2 << endl;
			while ( k1 < n && k2 < m ) {
				if ( compare( C[k1], D[k2] ) ) {
					ll TX = C[k1].x - C[j].x;
					ll TY = C[k1].y - C[j].y;
					if (TX * VY < TY * VX) {
						num++;
						//cout << A[i] << ' ' << C[j] << ' ' << C[k1] << endl;
					}
					k1++;
				}
				else {
					ll TX = D[k2].x - C[j].x;
					ll TY = D[k2].y - C[j].y;
					if (TX * VY < TY * VX) {
						VX = TX;
						VY = TY;
						//printf("Novi vektor pravca: [%d, %d] -> [%d, %d]\n", C[j].x, C[j].y, D[k2].x, D[k2].y);
					}
					k2++;
				}
			}
			while ( k1 < n ) {
				ll TX = C[k1].x - C[j].x;
				ll TY = C[k1].y - C[j].y;
				if (TX * VY < TY * VX) {
					num++;
					//cout << A[i] << ' ' << C[j] << ' ' << C[k1] << endl;
				}
				k1++;
			}
		}
	}
	printf("%d\n", num);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;

ll ox, oy;

struct point {
	ll x, y;
	bool blue;
	point() : x(0), y(0), blue(0) {}
	point(const ll x, const ll y) : x(x), y(y) {}

	bool operator < ( const point & Q ) const {
		if (x != Q.x) return x < Q.x;
		return y < Q.y;
	}

	friend ostream & operator << ( ostream & cout, point & Q ) {
		return cout << '[' << Q.x << ", " << Q.y << ']';
	}
} A[500], B[500], C[500], D[500];

inline bool compare( const point & P, const point & Q ) {
	point A( P.x - ox, P.y - oy ), B( Q.x - ox, Q.y - oy );
	if ( A.x * B.y == A.y * B.x ) return P.blue > Q.blue;
	else return A.x * B.y > A.y * B.x;
	//return A.x * B.y > A.y * B.x;
}

int main() {
	//freopen("napredna.in", "r", stdin);
	int n, m, num = 0;
	//scanf("%d%d", &n, &m);
	cin >> n >> m;
	for (int i = 0; i < n; i++) //scanf("%I64d%I64d", &A[i].x, &A[i].y);
		cin >> A[i].x >> A[i].y;
	for (int i = 0; i < m; i++) {
		//scanf("%I64d%I64d", &B[i].x, &B[i].y);
		cin >> B[i].x >> B[i].y;
		B[i].blue = 1;
	}
	sort( A, A + n );
	sort( B, B + m );
	for (int i = 0, zomg = 0; i < n - 2; i++) {
		while ( zomg < m && B[zomg] < A[i] ) zomg++;
		memcpy( C + i + 1, A + i + 1, sizeof(point) * (n - i - 1) );
		memcpy( D + zomg, B + zomg, sizeof(point) * (m - zomg) );
		ox = A[i].x;
		oy = A[i].y;
		sort( C + i + 1, C + n, compare );
		sort( D + zomg, D + m, compare );

		for (int j = i + 1; j < n - 1; j++) {
			ll VX = C[j].x - A[i].x;
			ll VY = C[j].y - A[i].y;

			int k1 = j + 1;
			int k2 = zomg;
			cout << k1 << ' ' << k2 << endl;
			while ( k1 < n && k2 < m ) {
				if ( compare( C[k1], D[k2] ) ) {
					ll TX = C[k1].x - C[j].x;
					ll TY = C[k1].y - C[j].y;
					if (TX * VY < TY * VX) {
						num++;
						//cout << A[i] << ' ' << C[j] << ' ' << C[k1] << endl;
					}
					k1++;
				}
				else {
					ll TX = D[k2].x - C[j].x;
					ll TY = D[k2].y - C[j].y;
					if (TX * VY < TY * VX) {
						VX = TX;
						VY = TY;
						//printf("Novi vektor pravca: [%d, %d] -> [%d, %d]\n", C[j].x, C[j].y, D[k2].x, D[k2].y);
					}
					k2++;
				}
			}
			while ( k1 < n ) {
				ll TX = C[k1].x - C[j].x;
				ll TY = C[k1].y - C[j].y;
				if (TX * VY < TY * VX) {
					num++;
					//cout << A[i] << ' ' << C[j] << ' ' << C[k1] << endl;
				}
				k1++;
			}
		}
	}
	printf("%d\n", num);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;

ll ox, oy;

struct point {
	ll x, y;
	point() : x(0), y(0) {}
	point(const ll x, const ll y) : x(x), y(y) {}

	bool operator < ( const point & Q ) const {
		if (x != Q.x) return x < Q.x;
		return y < Q.y;
	}
} A[500], B[500], C[500], D[500];

inline bool compare( const point & P, const point & Q ) {
	point A( P.x - ox, P.y - oy ), B( Q.x - ox, Q.y - oy );
	return A.x * B.y > A.y * B.x;
}

int main() {
	//freopen("napredna.in", "r", stdin);
	int n, m, num = 0;
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) scanf("%I64d%I64d", &A[i].x, &A[i].y);
	for (int i = 0; i < m; i++) scanf("%I64d%I64d", &B[i].x, &B[i].y);
	sort( A, A + n );
	sort( B, B + m );
	for (int i = 0, zomg = 0; i < n - 2; i++) {
		while ( zomg < m && B[zomg] < A[i] ) zomg++;
		memcpy( C + i + 1, A + i + 1, sizeof(point) * (n - i - 1) );
		memcpy( D + zomg, B + zomg, sizeof(point) * (m - zomg) );
		ox = A[i].x;
		oy = A[i].y;
		sort( C + i + 1, C + n, compare );
		sort( D + zomg, D + m, compare );

		for (int j = i + 1; j < n - 1; j++) {
			ll VX = C[j].x - A[i].x;
			ll VY = C[j].y - A[i].y;

			int k1 = j + 1;
			int k2 = zomg;
			while ( k1 < n && k2 < m ) {
				if ( compare( C[k1], D[k2] ) ) {
					ll TX = C[k1].x - C[j].x;
					ll TY = C[k1].y - C[j].y;
					if (TX * VY < TY * VX) num++;
					k1++;
				}
				else {
					ll TX = D[k2].x - C[j].x;
					ll TY = D[k2].y - C[j].y;
					if (TX * VY < TY * VX) {
						VX = TX;
						VY = TY;
					}
					k2++;
				}
			}
			while ( k1 < n ) {
				ll TX = C[k1].x - C[j].x;
				ll TY = C[k1].y - C[j].y;
				if (TX * VY < TY * VX) num++;
				k1++;
			}
		}
	}
	printf("%d\n", num);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long ll;

ll ox, oy;

struct point {
	ll x, y;
	bool blue;
	point() : x(0), y(0), blue(0) {}
	point(const ll x, const ll y) : x(x), y(y) {}

	bool operator < ( const point & Q ) const {
		if (x != Q.x) return x < Q.x;
		return y < Q.y;
	}

	friend ostream & operator << ( ostream & cout, point & Q ) {
		return cout << '[' << Q.x << ", " << Q.y << ']';
	}
} A[500], B[500], C[500], D[500];

inline bool compare( const point & P, const point & Q ) {
	point A( P.x - ox, P.y - oy ), B( Q.x - ox, Q.y - oy );
	if ( A.x * B.y == A.y * B.x ) return P.blue > Q.blue;
	else return A.x * B.y > A.y * B.x;
	//return A.x * B.y > A.y * B.x;
}

int main() {
	//freopen("napredna.in", "r", stdin);
	int n, m, num = 0;
	scanf("%d%d", &n, &m);
	//cin >> n >> m;
	for (int i = 0; i < n; i++) scanf("%I64d%I64d", &A[i].x, &A[i].y);
		//cin >> A[i].x >> A[i].y;
	for (int i = 0; i < m; i++) {
		scanf("%I64d%I64d", &B[i].x, &B[i].y);
		//cin >> B[i].x >> B[i].y;
		B[i].blue = 1;
	}
	sort( A, A + n );
	sort( B, B + m );
	for (int i = 0, zomg = 0; i < n - 2; i++) {
		while ( zomg < m && B[zomg] < A[i] ) zomg++;
		memcpy( C + i + 1, A + i + 1, sizeof(point) * (n - i - 1) );
		memcpy( D + zomg, B + zomg, sizeof(point) * (m - zomg) );
		ox = A[i].x;
		oy = A[i].y;
		sort( C + i + 1, C + n, compare );
		sort( D + zomg, D + m, compare );

		for (int j = i + 1; j < n - 1; j++) {
			ll VX = C[j].x - A[i].x;
			ll VY = C[j].y - A[i].y;

			int k1 = j + 1;
			int k2 = zomg;
			//cout << k1 << ' ' << k2 << endl;
			while ( k1 < n && k2 < m ) {
				if ( compare( C[k1], D[k2] ) ) {
					ll TX = C[k1].x - C[j].x;
					ll TY = C[k1].y - C[j].y;
					if (TX * VY < TY * VX) {
						num++;
						//cout << A[i] << ' ' << C[j] << ' ' << C[k1] << endl;
					}
					k1++;
				}
				else {
					ll TX = D[k2].x - C[j].x;
					ll TY = D[k2].y - C[j].y;
					if (TX * VY < TY * VX) {
						VX = TX;
						VY = TY;
						//printf("Novi vektor pravca: [%d, %d] -> [%d, %d]\n", C[j].x, C[j].y, D[k2].x, D[k2].y);
					}
					k2++;
				}
			}
			while ( k1 < n ) {
				ll TX = C[k1].x - C[j].x;
				ll TY = C[k1].y - C[j].y;
				if (TX * VY < TY * VX) {
					num++;
					//cout << A[i] << ' ' << C[j] << ' ' << C[k1] << endl;
				}
				k1++;
			}
		}
	}
	printf("%d\n", num);
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define maxn 1009
struct pt
{
	double x,y;
	bool red;
	pt(){}
	pt(double e1,double e2):x(e1),y(e2){}
}a[maxn],b[maxn],u[maxn],v[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline double xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline double xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>eps;
}
int n;
bool check(pt p)
{
	if(p.y==b[0].y)
	{
		if(p.x>b[0].x)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		minv=1e20;
		for(int j=i+1;j<n;j++)
		{
			angle=xmult(b[i],b[j],b[0])/dis(b[i],b[j])/dis(b[i],b[0]);
			if(b[j].red)
			{
				if(zero(angle-minv))
					while(1)
						printf("1111111111\n");
				if(angle<minv)
					cnt++;
			}
			else
				minv=min(minv,angle);
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%lf%lf",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%lf%lf",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
				check(u[j]);
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define maxn 1009
struct pt
{
	double x,y;
	bool red;
	pt(){}
	pt(double e1,double e2):x(e1),y(e2){}
}u[maxn],v[maxn],b[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline double xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline double xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>eps;
}
int n;
bool check(pt p)
{
	if(p.y==b[0].y)
	{
		if(p.x>b[0].x)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		minv=1e20;
		for(int j=i+1;j<n;j++)
		{
			angle=xmult(b[i],b[j],b[0])/dis(b[i],b[j])/dis(b[i],b[0]);
			if(b[j].red)
			{
				if(angle<minv)
					cnt++;
			}
			else
				minv=min(minv,angle);
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%lf%lf",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%lf%lf",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
				check(u[j]);
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define maxn 1009
struct pt
{
	double x,y;
	bool red;
	pt(){}
	pt(double e1,double e2):x(e1),y(e2){}
}a[maxn],b[maxn],u[maxn],v[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline double xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline double xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>eps;
}
int n;
bool check(pt p)
{
	if(zero(p.y-b[0].y))
	{
		if(p.x>b[0].x+eps)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		minv=1e20;
		for(int j=i+1;j<n;j++)
		{
			angle=xmult(b[i],b[j],b[0])/dis(b[i],b[j])/dis(b[i],b[0]);
			if(b[j].red)
			{
				if(zero(angle-minv))
					while(1)
						printf("1111111111\n");
				if(angle<minv)
					cnt++;
			}
			else
				minv=min(minv,angle);
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%lf%lf",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%lf%lf",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
				check(u[j]);
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define LL long long
#define maxn 1009
struct pt
{
	LL x,y;
	bool red;
	pt(){}
	pt(LL e1,LL e2):x(e1),y(e2){}
}a[maxn],b[maxn],u[maxn],v[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline LL xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline LL xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)+0.0);
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>0;
}
int n;
void check(pt p)
{
	if(p.y==b[0].y)
	{
		if(p.x>b[0].x)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		minv=1e20;
		for(int j=i+1;j<n;j++)
		{
			angle=xmult(b[i],b[j],b[0])/dis(b[i],b[j])/dis(b[i],b[0]);
			if(b[j].red)
			{
				if(zero(angle-minv))
					while(1)
						printf("1111111111\n");
				if(angle<minv)
					cnt++;
			}
			else
				minv=min(minv,angle);
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%I64d%I64d",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%I64d%I64d",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
			{
				if(j==i)
					continue;
				check(u[j]);
			}
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define LL long long
#define maxn 1009
struct pt
{
	LL x,y;
	bool red;
	pt(){}
	pt(LL e1,LL e2):x(e1),y(e2){}
}a[maxn],b[maxn],u[maxn],v[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline LL xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline LL xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)+0.0);
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>0;
}
int n;
void check(pt p)
{
	if(p.y==b[0].y)
	{
		if(p.x>b[0].x)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	bool flag;
	int tmp;
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		flag=false;
		for(int j=i+1;j<n;j++)
		{
			if(b[j].red)
			{
				if(flag==false||xmult(b[i],b[tmp],b[j])>eps)
					cnt++;
			}
			else
			{
				if(flag==false)
				{
					flag=true;
					tmp=j;
				}
				else
				{
					if(xmult(b[i],b[tmp],b[j])>eps)
						tmp=j;
				}
			}
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%I64d%I64d",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%I64d%I64d",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
				check(u[j]);
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define LL long long
#define maxn 1009
struct pt
{
	LL x,y;
	bool red;
	pt(){}
	pt(LL e1,LL e2):x(e1),y(e2){}
}a[maxn],b[maxn],u[maxn],v[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline LL xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline LL xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)+0.0);
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>0;
}
int n;
bool check(pt p)
{
	if(zero(p.y-b[0].y))
	{
		if(p.x>b[0].x+eps)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		minv=1e20;
		for(int j=i+1;j<n;j++)
		{
			angle=xmult(b[i],b[j],b[0])/dis(b[i],b[j])/dis(b[i],b[0]);
			if(b[j].red)
			{
				if(zero(angle-minv))
					while(1)
						printf("1111111111\n");
				if(angle<minv)
					cnt++;
			}
			else
				minv=min(minv,angle);
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%I64d%I64d",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%I64d%I64d",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
				check(u[j]);
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#include <math.h>
#define eps 1e-8
inline bool zero(const double &e){return fabs(e)<eps;}
#define maxn 1009
struct pt
{
	double x,y;
	bool red;
	pt(){}
	pt(double e1,double e2):x(e1),y(e2){}
	void out()
	{
		printf("(%d,%d) ",x,y);
	}
}u[maxn],v[maxn],b[maxn];
pt operator -(const pt &elem1,const pt &elem2)
{
	return pt(elem1.x-elem2.x,elem1.y-elem2.y);
}
inline double xmult(const pt &p1,const pt &p2)
{
	return p1.x*p2.y-p2.x*p1.y;
}
inline double xmult(const pt &p0,const pt &p1,const pt &p2)
{
	return xmult(p1-p0,p2-p0);
}
inline double dis(const pt &p1,const pt &p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
bool operator <(const pt &elem1,const pt &elem2)
{
	return xmult(b[0],elem1,elem2)>eps;
}
int n;
bool check(pt p)
{
	if(p.y==b[0].y)
	{
		if(p.x>b[0].x)
			b[n++]=p;
	}
	else if(p.y>b[0].y)
		b[n++]=p;
}
int calc()
{
	int cnt=0;
	sort(b+1,b+n);
	double minv,angle;
	/*
	printf("n is %d\n",n);
	for(int i=0;i<n;i++)
		b[i].out();
	printf("\n");
	*/
	for(int i=1;i<n;i++)
	{
		if(b[i].red==false)
			continue;
		minv=1e20;
		for(int j=i+1;j<n;j++)
		{
			angle=xmult(b[0],b[i],b[j])/dis(b[0],b[i])/dis(b[0],b[j]);
			if(b[j].red)
			{
				if(angle<minv)
					cnt++;
				/*
				b[0].out();b[i].out();b[j].out();
				printf("\n");
				printf("minv is %.6f\n",minv);
				*/
			}
			else
			{
				minv=min(minv,angle);
			}
		}
	}
	return cnt;
}
int main()
{
	int n1,n2;
	for(;;)
	{
		if(scanf("%d%d",&n1,&n2)==EOF)
			break;
		for(int i=0;i<n1;i++)
		{
			scanf("%lf%lf",&u[i].x,&u[i].y);
			u[i].red=true;
		}
		for(int i=0;i<n2;i++)
		{
			scanf("%lf%lf",&v[i].x,&v[i].y);
			v[i].red=false;
		}
		int res=0;
		for(int i=0;i<n1;i++)
		{
			n=0;
			b[n++]=u[i];
			for(int j=0;j<n1;j++)
				check(u[j]);
			for(int j=0;j<n2;j++)
				check(v[j]);
			res+=calc();
		}
		printf("%d\n",res);
	}
	return 0;
}


#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cfloat>
#include <numeric>

using namespace std;

const int oo = 0x3f3f3f3f;
const double eps = 1e-9;

typedef long long ll;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;

#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define FORD(i,a,b) for (int i = int(b)-1; i >= (a); i--)
#define FORIT(i,c) for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); i++)

struct Point {       //Punkt mit ganzzahligen Koordinaten
    ll x, y;
    Point(ll x=0, ll y=0) : x(x), y(y) {}
};

int ccw(Point p0, Point p1, Point p2) {
    long long c = (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
    if (c==0) return 0;
    return (c > 0) ? 1 : -1;
}

Point A[700];
Point B[700];

int Num[700][700];

int main() {
	int n=0;
	int m=0;
	scanf("%d%d",&n,&m);
	FOR(i,0,n)
	{
		scanf("%I64d%I64d",&A[i].x,&A[i].y);
	}
	FOR(i,0,m)
	{
		scanf("%I64d%I64d",&B[i].x,&B[i].y);
	}
	int Ref=0;
	FOR(i,0,n)
	{
		if(A[i].x<A[Ref].x||(A[i].x==A[Ref].x&&A[i].y<A[Ref].y))
			Ref=i;
	}
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			Num[i][j]=0;
			if(i!=Ref&&j!=Ref)
			{
				FOR(k,0,m)
				{
					int F=1;
					if(ccw(A[Ref],A[i],A[j])<0)
					{
						F*=-1;
					}
					if(ccw(A[Ref],A[i],B[k])==ccw(A[Ref],A[i],A[j])
						&&ccw(A[i],A[j],B[k])==ccw(A[i],A[j],A[Ref])
						&&ccw(A[Ref],A[j],B[k])==ccw(A[Ref],A[j],A[i]))
					{
						Num[i][j]+=F;
					}
				}
			}
			Num[j][i]=-Num[i][j];
		}
	}
	int Res=0;
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			FOR(k,0,j)
			{
				int Sum=Num[i][j]+Num[j][k]+Num[k][i];
				if(Sum==0)
				{
					Res++;
				}
			}
		}
	}
	printf("%d\n",Res);
	return 0;
}


#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cfloat>
#include <numeric>

using namespace std;

const int oo = 0x3f3f3f3f;
const double eps = 1e-9;

typedef long long ll;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;

#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define FORD(i,a,b) for (int i = int(b)-1; i >= (a); i--)
#define FORIT(i,c) for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); i++)

struct Point {       //Punkt mit ganzzahligen Koordinaten
    ll x, y;
    Point(ll x=0, ll y=0) : x(x), y(y) {}
};

int ccw(Point p0, Point p1, Point p2) {
    long long c = (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
    if (c==0) return 0;
    return (c > 0) ? 1 : -1;
}

Point A[700];
Point B[700];

int Num[700][700];

int main() {
	int n=0;
	int m=0;
	scanf("%d%d",&n,&m);
	FOR(i,0,n)
	{
		scanf("%lld%lld",&A[i].x,&A[i].y);
	}
	FOR(i,0,m)
	{
		scanf("%lld%lld",&B[i].x,&B[i].y);
	}
	int Ref=0;
	FOR(i,0,n)
	{
		if(A[i].x<A[Ref].x||(A[i].x==A[Ref].x&&A[i].y<A[Ref].y))
			Ref=i;
	}
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			Num[i][j]=0;
			if(i!=Ref&&j!=Ref)
			{
				FOR(k,0,m)
				{
					int F=1;
					if(ccw(A[Ref],A[i],A[j])<0)
					{
						F*=-1;
					}
					if(ccw(A[Ref],A[i],B[k])==ccw(A[Ref],A[i],A[j])
						&&ccw(A[i],A[j],B[k])==ccw(A[i],A[j],A[Ref])
						&&ccw(A[Ref],A[j],B[k])==ccw(A[Ref],A[j],A[i]))
					{
						Num[i][j]+=F;
					}
				}
			}
			Num[j][i]=-Num[i][j];
		}
	}
	int Res=0;
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			FOR(k,0,j)
			{
				int Sum=Num[i][j]+Num[j][k]+Num[k][i];
				if(Sum==0)
				{
					Res++;
				}
			}
		}
	}
	printf("%d\n",Res);
	return 0;
}


#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cfloat>
#include <numeric>

using namespace std;

const int oo = 0x3f3f3f3f;
const double eps = 1e-9;

typedef long long ll;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;

#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define FORD(i,a,b) for (int i = int(b)-1; i >= (a); i--)
#define FORIT(i,c) for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); i++)

struct Point {       //Punkt mit ganzzahligen Koordinaten
    ll x, y;
    Point(ll x=0, ll y=0) : x(x), y(y) {}
};

int ccw(Point p0, Point p1, Point p2) {
    double c = (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
    if (abs(c) <= eps) return 0;
    return (c > 0) ? 1 : -1;
}

Point A[700];
Point B[700];

int Num[700][700];

int main() {
	int n=0;
	int m=0;
	scanf("%d%d",&n,&m);
	FOR(i,0,n)
	{
		scanf("%lld%lld",&A[i].x,&A[i].y);
	}
	FOR(i,0,m)
	{
		scanf("%lld%lld",&B[i].x,&B[i].y);
	}
	int Ref=0;
	FOR(i,0,n)
	{
		if(A[i].x<A[Ref].x||(A[i].x==A[Ref].x&&A[i].y<A[Ref].y))
			Ref=i;
	}
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			Num[i][j]=0;
			if(i!=Ref&&j!=Ref)
			{
				FOR(k,0,m)
				{
					int F=1;
					if(ccw(A[Ref],A[i],A[j])<0)
					{
						F*=-1;
					}
					if(ccw(A[Ref],A[i],B[k])==ccw(A[i],A[j],B[k])
						&&ccw(A[Ref],A[i],B[k])==ccw(A[j],A[Ref],B[k]))
					{
						Num[i][j]+=F;
					}
				}
			}
			Num[j][i]=-Num[i][j];
		}
	}
	int Res=0;
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			FOR(k,0,j)
			{
				int Sum=Num[i][j]+Num[j][k]+Num[k][i];
				if(Sum==0)
				{
					Res++;
				}
			}
		}
	}
	printf("%d\n",Res);
	return 0;
}


#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cfloat>
#include <numeric>

using namespace std;

const int oo = 0x3f3f3f3f;
const double eps = 1e-9;

typedef long long ll;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;

#define sz(c) int((c).size())
#define all(c) (c).begin(), (c).end()
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define FORD(i,a,b) for (int i = int(b)-1; i >= (a); i--)
#define FORIT(i,c) for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); i++)

struct Point {       //Punkt mit ganzzahligen Koordinaten
    ll x, y;
    Point(ll x=0, ll y=0) : x(x), y(y) {}
};

int ccw(Point p0, Point p1, Point p2) {
    long long c = (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
    if (c==0) return 0;
    return (c > 0) ? 1 : -1;
}

Point A[700];
Point B[700];

int Num[700][700];

int main() {
	int n=0;
	int m=0;
	scanf("%d%d",&n,&m);
	FOR(i,0,n)
	{
		scanf("%I64d%I64d",&A[i].x,&A[i].y);
	}
	FOR(i,0,m)
	{
		scanf("%I64d%I64d",&B[i].x,&B[i].y);
	}
	int Ref=0;
	FOR(i,0,n)
	{
		if(A[i].x<A[Ref].x||(A[i].x==A[Ref].x&&A[i].y<A[Ref].y))
			Ref=i;
	}
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			Num[i][j]=0;
			if(i!=Ref&&j!=Ref)
			{
				FOR(k,0,m)
				{
					int F=1;
					if(ccw(A[Ref],A[i],A[j])<0)
					{
						F*=-1;
					}
					int CW=ccw(A[Ref],A[i],A[j]);
					if(ccw( A[Ref],A[i],B[k])==CW
						&&ccw(A[i],A[j],B[k])==CW
						&&ccw(A[j],A[Ref],B[k])==CW)
					{
						Num[i][j]+=F;
					}
				}
			}
			Num[j][i]=-Num[i][j];
		}
	}
	int Res=0;
	FOR(i,0,n)
	{
		FOR(j,0,i)
		{
			FOR(k,0,j)
			{
				int Sum=Num[i][j]+Num[j][k]+Num[k][i];
				if(Sum==0)
				{
					Res++;
				}
			}
		}
	}
	printf("%d\n",Res);
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <complex>
using namespace std;
typedef complex<int> pnt;
pnt Red[500],Blue[500];
int Cnt[500][500];
bool comp(const pnt& a,const pnt& b)
{
	return a.real() < b.real();
}
int outerSign(const pnt& a,const pnt& b)
{
	//assume that result is non zero.
	return ((long long)a.real() * b.imag() - (long long)a.imag() * b.real()) > 0 ? 1: -1;
}
int iSgn(int i)
{
	return (i>0)?1:(i<0)?-1:0;
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for (int q=0;q<n;++q)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		Red[q] = pnt(a,b);
	}
	for (int q=0;q<m;++q)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		Blue[q] = pnt(a,b);
	}
	sort(Red,Red+n,comp);
	sort(Blue,Blue+m,comp);
	int begin = 0;
	for (int q=0;q<n;++q)
	{
		while (begin < m && Blue[begin].real() < Red[q].real()) begin++;
		for (int w=q+1;w<n;++w)
		{
			//the # of blue point below the line [ q,w )
			for (int e=begin;e<m;++e)
			{
				//if ( Blue[e].real() < Red[q].real() ) continue;
				if ( Blue[e].real() >= Red[w].real() ) break;
				if ( outerSign(Blue[e]-Red[q], Red[w]-Red[q]) > 0 )
				{
					Cnt[q][w]++;
					Cnt[w][q]++;
				}
			}
		}
	}
	int ret=0;
	for (int q=0;q<n;++q) for (int w=q+1;w<n;++w) for (int e=w+1;e<n;++e)
	{
		//q->w->e
		//triSign + & dx + : lowerChain. => -
		int triSign = outerSign(Red[w]-Red[q],Red[e]-Red[q]);
		int blues = - triSign * iSgn(Red[w].real()-Red[q].real()) * Cnt[q][w]
					- triSign * iSgn(Red[e].real()-Red[w].real()) * Cnt[w][e]
					- triSign * iSgn(Red[q].real()-Red[e].real()) * Cnt[e][q];
		//cout << Red[q] << Red[w] << Red[e] << blues << endl;
		if (!blues)
			ret++;
	}
	printf("%d\n",ret);
	return 0;
}


#include <complex>
#include <vector>
#include <map>
#include <math.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef complex<long long> pnt;

long long inner(const pnt& a,const pnt& b)
{
	return a.imag()*b.imag()+a.real()*b.real();
}
long long outer(const pnt& a,const pnt& b)
{
	return a.real()*b.imag()-a.imag()*b.real();
}

int C[505][4];
int TC[505][4];

int getColumnSumC(int a,int b,int k)
{
	//def :: TC[a][b] = TC[a-1][b] + C[a][b]
	int ret = TC[b][k];
	if (a) ret -= TC[a-1][k];
	return ret;
}

int getCombiOrder(int low,int high,int k,int *list)//list should be sorted.
{
	if (!k) return 0;
	int n = high - low + 1;
	int h = *list;
	// n-1 C k-1 + n-2 C k-1 + ... n-(h-low) C k - 1
	int ret = 0;
	if (low<h) ret += getColumnSumC(n-(h-low),n-1,k-1);
	return ret + getCombiOrder(h+1,high,k-1,list+1);
}

int n,m;
pnt red[500],blue[500];

struct newPnt
{
	pnt pos;
	int index;
	int isRed;
	int isOriginal;
	bool operator<(const newPnt& obj) const
	{
		return outer(pos,obj.pos)>0;
	}
};

short cum[22000000];

int main()
{
	scanf("%d %d",&n,&m);
	for (int q=0;q<=n;++q)
		for (int w=0;w<=q && w<=3;++w)
		{
			if (w==0 || w==q) C[q][w]=1;
			else C[q][w]=C[q-1][w-1]+C[q-1][w];
			if (q==w) TC[q][w] = C[q][w];
			else TC[q][w]=TC[q-1][w]+C[q][w];
		}
	for (int q=0;q<n;++q)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		red[q] = pnt(a,b);
	}
	for (int q=0;q<m;++q)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		blue[q] = pnt(a,b);
	}

	for (int q=0;q<n;++q)
	{
		vector<newPnt> list;
		newPnt tmp;
		for (int w=0;w<n;++w)
		{
			if (q==w) continue;
			tmp.pos = red[w] - red[q];
			tmp.isRed = 1;
			tmp.index = w;
			if (tmp.pos.imag()<0)
			{
				tmp.pos = -tmp.pos;
				tmp.isOriginal = 0;
			}
			else tmp.isOriginal = 1;
			list.push_back(tmp);
		}
		for (int w=0;w<m;++w)
		{
			tmp.pos = blue[w] - red[q];
			tmp.isRed = 0;
			tmp.index = w;
			if (tmp.pos.imag()<0)
			{
				tmp.pos = -tmp.pos;
				tmp.isOriginal = 0;
			}
			else tmp.isOriginal = 1;
			list.push_back(tmp);
		}
		sort(list.begin(),list.end());
		for (int w=0;w<list.size();++w)
		{
			if (list[w].isRed == 0) continue;
			int cnt = 0;
			for (int e=w+1;e<list.size();++e)
			{
				if (list[e].isRed == 0) { cnt++; continue; }
				int com[3] = {q,list[w].index,list[e].index};
				sort(com,com+3);
				if (list[w].isOriginal==list[e].isOriginal)
					cum[getCombiOrder(0,n-1,3,com)]+=cnt;
				else
					cum[getCombiOrder(0,n-1,3,com)]+=m-cnt;
			}
		}
	}

	int ret=0;
	for (int q=0;q<C[n][3];++q)
		if (cum[q]==m)
			ret++;
	printf("%d\n",ret);
}


#include <complex>
#include <vector>
#include <map>
#include <math.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef complex<long long> pnt;

long long inner(const pnt& a,const pnt& b)
{
	return a.imag()*b.imag()+a.real()*b.real();
}
long long outer(const pnt& a,const pnt& b)
{
	return a.real()*b.imag()-a.imag()*b.real();
}

int C[505][4];
int TC[505][4];

int getColumnSumC(int a,int b,int k)
{
	//def :: TC[a][b] = TC[a-1][b] + C[a][b]
	int ret = TC[b][k];
	if (a) ret -= TC[a-1][k];
	return ret;
}

int getCombiOrder(int low,int high,int k,int *list)//list should be sorted.
{
	if (!k) return 0;
	int h = *list;
	int ret = 0;
	if (low<h) ret += getColumnSumC((high + 1 - h),high - low,k-1);
	return ret + getCombiOrder(h+1,high,k-1,list+1);
}

int n,m;
pnt red[500],blue[500];

struct newPnt
{
	pnt pos;
	int index;
	int isRed;
	int isOriginal;
	bool operator<(const newPnt& obj) const
	{
		return outer(pos,obj.pos)>0;
	}
};

short cum[22000000];

int main()
{
	scanf("%d %d",&n,&m);
	for (int q=0;q<=n;++q)
		for (int w=0;w<=q && w<=3;++w)
		{
			if (w==0 || w==q) C[q][w]=1;
			else C[q][w]=C[q-1][w-1]+C[q-1][w];
			if (q==w) TC[q][w] = C[q][w];
			else TC[q][w]=TC[q-1][w]+C[q][w];
		}
	for (int q=0;q<n;++q)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		red[q] = pnt(a,b);
	}
	for (int q=0;q<m;++q)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		blue[q] = pnt(a,b);
	}

	for (int q=0;q<n;++q)
	{
		vector<newPnt> list;
		newPnt tmp;
		for (int w=0;w<n;++w)
		{
			if (q==w) continue;
			tmp.pos = red[w] - red[q];
			tmp.isRed = 1;
			tmp.index = w;
			if (tmp.pos.imag()<0)
			{
				tmp.pos = -tmp.pos;
				tmp.isOriginal = 0;
			}
			else tmp.isOriginal = 1;
			list.push_back(tmp);
		}
		for (int w=0;w<m;++w)
		{
			tmp.pos = blue[w] - red[q];
			tmp.isRed = 0;
			tmp.index = w;
			if (tmp.pos.imag()<0)
			{
				tmp.pos = -tmp.pos;
				tmp.isOriginal = 0;
			}
			else tmp.isOriginal = 1;
			list.push_back(tmp);
		}
		sort(list.begin(),list.end());
		for (int w=0;w<list.size();++w)
		{
			if (list[w].isRed == 0) continue;
			int cnt = 0;
			int com[3];
			int a = q;
			int b = list[w].index;
			if (a>b) swap(a,b);
			for (int e=w+1;e<list.size();++e)
			{
				if (list[e].isRed == 0) { cnt++; continue; }
				if (list[e].index < a)		com[0]=list[e].index,com[1]=a,com[2]=b;
				else if (list[e].index < b) com[0]=a,com[1]=list[e].index,com[2]=b;
				else						com[0]=a,com[1]=b,com[2]=list[e].index;
				if (list[w].isOriginal==list[e].isOriginal)
					cum[getCombiOrder(0,n-1,3,com)]+=cnt;
				else
					cum[getCombiOrder(0,n-1,3,com)]+=m-cnt;
			}
		}
	}

	int ret=0;
	for (int q=0;q<C[n][3];++q)
		if (cum[q]==m)
			ret++;
	printf("%d\n",ret);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define MAXN 550
struct Point
{
    int x,y,color;
}p[MAXN<<1],pt[MAXN<<1],ct;
int n,m;
double a[MAXN<<1];
bool cmp(const int i,const int j)
{
    return a[i]<a[j];
}
ll xmult(Point p1,Point p2,Point p0)
{
    return 1ll*(p1.x-p0.x)*(p2.y-p0.y)-1ll*(p1.y-p0.y)*(p2.x-p0.x);
}
bool side(Point p0,Point p1,Point p2)
{
    return xmult(p0,p1,p2)<0;
}
bool in(Point p0,Point p1,Point p2,Point p3)
{
    bool tmp=side(p0,p1,p2);
    return tmp==side(p0,p2,p3)&&tmp==side(p0,p3,p1);
}
int r[MAXN<<1];
int sol(int n)
{
    for(int i=0;i<n;i++)
    {
        r[i]=i;
        a[i]=atan2(p[i].y-ct.y,p[i].x-ct.x);
    }
    sort(r,r+n,cmp);
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(p[r[i]].color==2) continue;
        Point blue;
        blue.color=-1;
        int j=i+1;
        if(j>=n) j=0;
        while(true)
        {
            if(xmult(p[r[i]],p[r[j]],ct)<=0) break;
            if(p[r[j]].color==2)
            {
                if(blue.color==-1||side(blue,p[r[j]],p[r[i]])!=side(ct,p[r[j]],p[r[i]]))
                    blue=p[r[j]];
            }
            else
            {
                if(blue.color==-1||!in(blue,ct,p[r[i]],p[r[j]])) ans++;
            }
            j++;
            if(j>=n) j=0;
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=1;
    }
    for(int i=n+1;i<=n+m;i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=2;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int cnt=0;
        for(int j=i+1;j<=n+m;j++) p[cnt++]=pt[j];
        ct=pt[i];
        ans+=sol(cnt);
    }
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define MAXN 550
int ctx,cty;
struct Point
{
    int x,y,color;
    Point operator -(const Point &p) const
    {
        Point ans;
        ans.x=x-p.x,ans.y=y-p.y;
        ans.color=color;
        return ans;
    }
    bool operator < (const Point& b) const
    {
        if(y<=0&&b.y<=0||y>0&&b.y>0) return x*b.y>y*b.x;
        return y<b.y;
    }
} p[MAXN<<1],pt[MAXN<<1],ct;
int n,m;
int xx[MAXN<<1];
ll xmult(Point p1,Point p2,Point p0)
{
    return 1ll*(p1.x-p0.x)*(p2.y-p0.y)-1ll*(p1.y-p0.y)*(p2.x-p0.x);
}
bool side(Point p0,Point p1,Point p2)
{
    return xmult(p0,p1,p2)<0;
}
bool in(Point p0,Point p1,Point p2,Point p3)
{
    bool tmp=side(p0,p1,p2);
    return tmp==side(p0,p2,p3)&&tmp==side(p0,p3,p1);
}
int sol(int n)
{
    sort(p,p+n);
    ct.x=0;ct.y=0;
    int ans=0;
    for(int i=0; i<n; i++)
    {
        if(p[i].color==2) continue;
        Point blue;
        blue.color=-1;
        int j=i+1;
        if(j>=n) j=0;
        while(true)
        {
            if(xmult(p[i],p[j],ct)<=0) break;
            if(p[j].color==2)
            {
                if(blue.color==-1||side(blue,p[j],p[i])!=side(ct,p[j],p[i]))
                    blue=p[j];
            }
            else
            {
                if(blue.color==-1||!in(blue,ct,p[i],p[j])) ans++;
            }
            j++;
            if(j>=n) j=0;
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=1;
    }
    for(int i=n+1; i<=n+m; i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=2;
    }
    int ans=0;
    for(int i=1; i+2<=n; i++)
    {
        int cnt=0;
        ct=pt[i];
        for(int j=i+1; j<=n+m; j++) p[cnt++]=pt[j]-ct;
        ans+=sol(cnt);
    }
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define MAXN 550
int ctx,cty;
struct Point
{
    int x,y,color,xx;
    void cal()
    {
        int tmpx=x-ctx,tmpy=y-cty;
        if(tmpx==0&&tmpy==0) xx=0;
        else if(tmpx<=0&&tmpy<0) xx=0;
        else if(tmpx>0&&tmpy<=0) xx=1;
        else if(tmpx>=0&&tmpy>0) xx=2;
        else xx=3;
    }
}p[MAXN<<1],pt[MAXN<<1],ct;
int n,m;
int xx[MAXN<<1];
ll xmult(Point p1,Point p2,Point p0)
{
    return 1ll*(p1.x-p0.x)*(p2.y-p0.y)-1ll*(p1.y-p0.y)*(p2.x-p0.x);
}
bool cmp(const int i,const int j)
{
    if(p[i].xx!=p[j].xx) return p[i].xx<p[j].xx;
    return xmult(p[i],p[j],ct)>0;
}
bool side(Point p0,Point p1,Point p2)
{
    return xmult(p0,p1,p2)<0;
}
bool in(Point p0,Point p1,Point p2,Point p3)
{
    bool tmp=side(p0,p1,p2);
    return tmp==side(p0,p2,p3)&&tmp==side(p0,p3,p1);
}
int r[MAXN<<1];
int sol(int n)
{
    ctx=ct.x,cty=ct.y;
    for(int i=0;i<n;i++) r[i]=i,p[i].cal();
    sort(r,r+n,cmp);
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(p[r[i]].color==2) continue;
        Point blue;
        blue.color=-1;
        int j=i+1;
        if(j>=n) j=0;
        while(true)
        {
            if(xmult(p[r[i]],p[r[j]],ct)<=0) break;
            if(p[r[j]].color==2)
            {
                if(blue.color==-1||side(blue,p[r[j]],p[r[i]])!=side(ct,p[r[j]],p[r[i]]))
                    blue=p[r[j]];
            }
            else
            {
                if(blue.color==-1||!in(blue,ct,p[r[i]],p[r[j]])) ans++;
            }
            j++;
            if(j>=n) j=0;
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=1;
    }
    for(int i=n+1;i<=n+m;i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=2;
    }
    int ans=0;
    for(int i=1;i+2<=n;i++)
    {
        int cnt=0;
        for(int j=i+1;j<=n+m;j++) p[cnt++]=pt[j];
        ct=pt[i];
        ans+=sol(cnt);
    }
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define MAXN 550
struct Point
{
	int x,y,color;
}p[MAXN<<1],pt[MAXN<<1],ct;
int n,m;
bool cmp(const Point p1,const Point p2)
{
	return atan2(p1.y-ct.y,p1.x-ct.x)<atan2(p2.y-ct.y,p2.x-ct.x);
}
ll xmult(Point p1,Point p2,Point p0)
{
	return 1ll*(p1.x-p0.x)*(p2.y-p0.y)-1ll*(p1.y-p0.y)*(p2.x-p0.x);
}
bool side(Point p0,Point p1,Point p2)
{
	return xmult(p0,p1,p2)<0;
}
bool in(Point p0,Point p1,Point p2,Point p3)
{
	bool tmp=side(p0,p1,p2);
	return tmp==side(p0,p2,p3)&&tmp==side(p0,p3,p1);
}
int sol(int n)
{
	sort(p,p+n,cmp);
	int ans=0;
	for(int i=0;i<n;i++)
	{
		if(p[i].color==2) continue;
		Point blue;
		blue.color=-1;
		int j=i+1;
		if(j>=n) j=0;
		while(true)
		{
			if(xmult(p[i],p[j],ct)<=0) break;
			if(p[j].color==2)
			{
				if(blue.color==-1||side(blue,p[j],p[i])!=side(ct,p[j],p[i]))
					blue=p[j];
			}
			else
			{
				if(blue.color==-1||!in(blue,ct,p[i],p[j])) ans++;
			}
			j++;
			if(j>=n) j=0;
		}
	}
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&pt[i].x,&pt[i].y);
		pt[i].color=1;
	}
	for(int i=n+1;i<=n+m;i++)
	{
		scanf("%d%d",&pt[i].x,&pt[i].y);
		pt[i].color=2;
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		int cnt=0;
		for(int j=i+1;j<=n+m;j++) p[cnt++]=pt[j];
		ct=pt[i];
		ans+=sol(cnt);
	}
	printf("%d\n",ans);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define MAXN 550
int ctx,cty;
struct Point
{
    int x,y,color;
    Point operator -(const Point &p) const
    {
        Point ans;
        ans.x=x-p.x,ans.y=y-p.y;
        ans.color=color;
        return ans;
    }
    bool operator < (const Point& b) const
    {
        if(y<=0&&b.y<=0||y>0&&b.y>0) return 1ll*x*b.y>1ll*y*b.x;
        return y<b.y;
    }
} p[MAXN<<1],pt[MAXN<<1],ct;
int n,m;
int xx[MAXN<<1];
ll xmult(Point p1,Point p2,Point p0)
{
    return 1ll*(p1.x-p0.x)*(p2.y-p0.y)-1ll*(p1.y-p0.y)*(p2.x-p0.x);
}
bool side(Point p0,Point p1,Point p2)
{
    return xmult(p0,p1,p2)<0;
}
bool in(Point p0,Point p1,Point p2,Point p3)
{
    bool tmp=side(p0,p1,p2);
    return tmp==side(p0,p2,p3)&&tmp==side(p0,p3,p1);
}
int sol(int n)
{
    sort(p,p+n);
    int ans=0;
    for(int i=0; i<n; i++)
    {
        if(p[i].color==2) continue;
        Point blue;
        blue.color=-1;
        int j=i+1;
        if(j>=n) j=0;
        while(true)
        {
            if(xmult(p[i],p[j],ct)<=0) break;
            if(p[j].color==2)
            {
                if(blue.color==-1||side(blue,p[j],p[i])!=side(ct,p[j],p[i]))
                    blue=p[j];
            }
            else
            {
                if(blue.color==-1||!in(blue,ct,p[i],p[j])) ans++;
            }
            j++;
            if(j>=n) j=0;
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=1;
    }
    for(int i=n+1; i<=n+m; i++)
    {
        scanf("%d%d",&pt[i].x,&pt[i].y);
        pt[i].color=2;
    }
    int ans=0;
    for(int i=1; i+2<=n; i++)
    {
        int cnt=0;
        for(int j=i+1; j<=n+m; j++) p[cnt++]=pt[j]-pt[i];
        ans+=sol(cnt);
    }
    printf("%d\n",ans);
    return 0;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < long long , long long > ii;

long long f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff < red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff <= red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[i].ss) > (xanh[k].ff - red[i].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if (f[i][j] + f[j][k] == f[i][k])
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff <= red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff < red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[j].ss) >= (xanh[k].ff - red[j].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] - f[i][k] + f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff < red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff <= red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[i].ss) > (xanh[k].ff - red[i].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] - f[i][k] + f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff <= red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff <= red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[i].ss) > (xanh[k].ff - red[i].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] - f[i][k] + f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < long long , long long > ii;

long long f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff < red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff <= red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[i].ss) < (xanh[k].ff - red[i].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if (f[i][j] + f[j][k] == f[i][k])
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff <= red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff < red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[j].ss) >= (xanh[k].ff - red[j].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] - f[i][k] + f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff < red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff <= red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[i].ss) > (xanh[k].ff - red[i].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if (f[i][j] + f[j][k] == f[i][k])
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff < red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff < red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[j].ss) >= (xanh[k].ff - red[j].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] - f[i][k] + f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
//	freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff <= red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff < red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[j].ss) >= (xanh[k].ff - red[j].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] + f[i][k] - f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include<iostream>
using namespace std;
#define ff first
#define ss second

typedef pair < int , int > ii;

int f[501][501];
ii red[501], xanh[501];

int main()
{
	//freopen("test.inp", "r", stdin);
	int n, m, ans = 0;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	cin >> red[i].ff >> red[i].ss;
	for(int i=1;i<=m;i++)
	cin >> xanh[i].ff >> xanh[i].ss;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(red[i].ff < red[j].ff)
			{
				for(int k=1;k<=m;k++)
					if(red[i].ff < xanh[k].ff && xanh[k].ff <= red[j].ff && (red[j].ff - red[i].ff) * (xanh[k].ss - red[j].ss) > (xanh[k].ff - red[j].ff) * (red[j].ss - red[i].ss))
						f[i][j]++;
				f[j][i] = -f[i][j];
			}
		}
	}
	for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            for (int k=j+1;k<=n;k++)
            	if(f[j][k] - f[i][k] + f[i][j] == 0)
            		ans++;
    cout << ans;
}


#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)

const int N = 500;

int rx[N], ry[N];
int bx[N], by[N];
int bal[N][N];
long long rbx[N][N];
long long rby[N][N];

int main()
{
	int n, m;

	cin >> n >> m;

	FOR(i, 0, n) cin >> rx[i] >> ry[i];
	FOR(i, 0, m) cin >> bx[i] >> by[i];

	FOR(i, 0, n) FOR(j, 0, m) {
		rbx[i][j] = rx[i] - bx[j];
		rby[i][j] = ry[i] - by[j];
	}

	FOR(i, 0, n) FOR(j, 0, n) {
		int x1 = min(rx[i], rx[j]);
		int x2 = max(rx[i], rx[j]);
		FOR(k, 0, m) if (x1 <= bx[k] && bx[k] < x2) {
			bal[i][j] += rbx[j][k] * rby[i][k] > rby[j][k] * rbx[i][k] ? 1 : -1;
		}
	}

	int res = 0;
	FOR(i, 0, n) FOR(j, i + 1, n) FOR(k, j + 1, n)
		res += bal[i][j] + bal[j][k] + bal[k][i] == 0;
	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	long long x, y;
	Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	long long operator % (const Point &op) const
	{
		return x * op.y - y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

Point ba[500][500];
Point aa[500][500];

int main()
{
	int n, m;
	cin >> n >> m;

	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}

	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < m; ++j)
			ba[i][j] = b[i] - a[j];

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			aa[i][j] = a[j] - a[i];

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % ba[k][i]) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	int cur1[16];
	int cur2[16];

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			Copy(cur1, toLeft[i][j]);
			Copy(cur2, toLeft[j][i]);
			for (int k = j + 1; k < n; ++k)
			{
				//if (ToLeft(a[i], a[j], a[k]))
				if (aa[i][j] % aa[i][k] > 0)
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[i][j][t] & toLeft[j][k][t] & toLeft[k][i][t])
						{
							--res;
							break;
						}
					}
				}
				else
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[j][i][t] & toLeft[k][j][t] & toLeft[i][k][t])
						{
							--res;
							break;
						}
					}
				}
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	long long x, y;
	Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	long long operator % (const Point &op) const
	{
		return x * op.y - y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

Point ba[500][500];
Point aa[500][500];

Point a[500];
Point b[500];

int main()
{
	int n, m;
	cin >> n >> m;

//	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}
//	random_shuffle(a.begin(), a.end());

//	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}
//	random_shuffle(b.begin(), b.end());

	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			ba[i][j] = b[i] - a[j];

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			aa[i][j] = a[j] - a[i];

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % ba[k][i]) > 0)
				//if (aij % (b[k] - a[i]) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				//if (ToLeft(a[i], a[j], a[k]))
				if (aa[i][j] % aa[i][k] > 0)
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[i][j][t] & toLeft[j][k][t] & toLeft[k][i][t])
						{
							--res;
							break;
						}
					}
				}
				else
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[j][i][t] & toLeft[k][j][t] & toLeft[i][k][t])
						{
							--res;
							break;
						}
					}
				}
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)

const int N = 500;

int rx[N], ry[N];
int bx[N], by[N];
int bal[N][N];
double rbx[N][N];
double rby[N][N];

int main()
{
	int n, m;

	cin >> n >> m;

	FOR(i, 0, n) cin >> rx[i] >> ry[i];
	FOR(i, 0, m) cin >> bx[i] >> by[i];

	FOR(i, 0, n) FOR(j, 0, m) {
		rbx[i][j] = rx[i] - bx[j];
		rby[i][j] = ry[i] - by[j];
	}

	FOR(i, 0, n) FOR(j, 0, n) {
		int x1 = min(rx[i], rx[j]);
		int x2 = max(rx[i], rx[j]);
		FOR(k, 0, m) if (x1 <= bx[k] && bx[k] < x2) {
			bal[i][j] += rbx[j][k] * rby[i][k] > rby[j][k] * rbx[i][k] ? 1 : -1;
		}
	}

	int res = 0;
	FOR(i, 0, n) FOR(j, i + 1, n) FOR(k, j + 1, n)
		res += bal[i][j] + bal[j][k] + bal[k][i] == 0;
	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	long long x, y;
	inline Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	inline Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	inline long long operator % (const Point &op) const
	{
		return x * op.y - y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

Point ba[500][500];
Point aa[500][500];

Point a[500];
Point b[500];

int main()
{
	int n, m;
	cin >> n >> m;

//	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}
//	random_shuffle(a.begin(), a.end());

//	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}
//	random_shuffle(b.begin(), b.end());

	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			ba[i][j] = b[i] - a[j];

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			aa[i][j] = a[j] - a[i];

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % ba[k][i]) > 0)
				//if (aij % (b[k] - a[i]) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				//if (ToLeft(a[i], a[j], a[k]))
				if (aa[i][j] % aa[i][k] > 0)
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[i][j][t] & toLeft[j][k][t] & toLeft[k][i][t])
						{
							--res;
							break;
						}
					}
				}
				else
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[j][i][t] & toLeft[k][j][t] & toLeft[i][k][t])
						{
							--res;
							break;
						}
					}
				}
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	int x, y;
	inline Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	inline Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	inline long long operator % (const Point &op) const
	{
		return (long long)x * op.y - (long long)y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

Point ba[500][500];
Point aa[500][500];

Point a[500];
Point b[500];

int main()
{
	int n, m;
	cin >> n >> m;

//	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}
//	random_shuffle(a.begin(), a.end());

//	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}
//	random_shuffle(b.begin(), b.end());

	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			ba[i][j] = b[i] - a[j];

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			aa[i][j] = a[j] - a[i];

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % ba[k][i]) > 0)
				//if (aij % (b[k] - a[i]) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				//if (ToLeft(a[i], a[j], a[k]))
				if (aa[i][j] % aa[i][k] > 0)
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[i][j][t] & toLeft[j][k][t] & toLeft[k][i][t])
						{
							--res;
							break;
						}
					}
				}
				else
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[j][i][t] & toLeft[k][j][t] & toLeft[i][k][t])
						{
							--res;
							break;
						}
					}
				}
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>

using namespace std;

struct Point
{
	long long x, y;
	Point (long long x = 0, long long y = 0) : x(x), y(y) {}
	Point operator-(Point op) {
		return Point(x - op.x, y - op.y);
	}
	long long operator % (Point op) {
		return x * op.y - y * op.x;
	}
};

int Sign(long long x)
{
	return x < 0 ? -1 : x > 0 ? 1 : 0;
}

istream &operator >> (istream &in, Point &v) {
	in >> v.x >> v.y;
}

template<class T>
istream &operator >> (istream &in, vector<T> &v) {
	for (int i = 0; i < v.size(); ++i) {
		in >> v[i];
	}
}

int main() {
	int n, m;
	cin >> n >> m;

	vector<Point> red(n);
	cin >> red;

	vector<Point> blue(m);
	cin >> blue;

	vector< vector<int> > balance(n, vector<int>(n, 0));
	for (int i = 0; i < red.size(); ++i) {
		for (int j = 0; j < red.size(); ++j) {
			if (red[i].x != red[i].y) {
				int x1 = min(red[i].x, red[j].x);
				int x2 = max(red[i].x, red[j].x);
				for (int k = 0; k < blue.size(); ++k) {
					if (x1 <= blue[k].x && blue[k].x < x2) {
						balance[i][j] += Sign((blue[k] - red[i]) % (red[j] - red[i]));
					}
				}
			}
		}
	}

	int res = 0;
	for (int i = 0; i < red.size(); ++i) {
		for (int j = i + 1; j < red.size(); ++j) {
			for (int k = j + 1; k < red.size(); ++k) {
				res += balance[i][j] + balance[j][k] + balance[k][i] == 0;
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	long long x, y;
	Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	long long operator % (const Point &op) const
	{
		return x * op.y - y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

Point ba[500][500];
Point aa[500][500];

int main()
{
	int n, m;
	cin >> n >> m;

	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}

	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}

	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			ba[i][j] = b[i] - a[j];

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			aa[i][j] = a[j] - a[i];

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % ba[k][i]) > 0)
				//if (aij % (b[k] - a[i]) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				//if (ToLeft(a[i], a[j], a[k]))
				if (aa[i][j] % aa[i][k] > 0)
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[i][j][t] & toLeft[j][k][t] & toLeft[k][i][t])
						{
							--res;
							break;
						}
					}
				}
				else
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[j][i][t] & toLeft[k][j][t] & toLeft[i][k][t])
						{
							--res;
							break;
						}
					}
				}
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	long long x, y;
	Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	long long operator % (const Point &op) const
	{
		return x * op.y - y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

Point ba[500][500];
Point aa[500][500];

int main()
{
	int n, m;
	cin >> n >> m;

	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}
	random_shuffle(a.begin(), a.end());

	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}
	random_shuffle(b.begin(), b.end());

	for (int i = 0; i < m; ++i)
		for (int j = 0; j < n; ++j)
			ba[i][j] = b[i] - a[j];

	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			aa[i][j] = a[j] - a[i];

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % ba[k][i]) > 0)
				//if (aij % (b[k] - a[i]) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				//if (ToLeft(a[i], a[j], a[k]))
				if (aa[i][j] % aa[i][k] > 0)
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[i][j][t] & toLeft[j][k][t] & toLeft[k][i][t])
						{
							--res;
							break;
						}
					}
				}
				else
				{
					++res;
					for (int t = 0; t < 16; ++t)
					{
						if (toLeft[j][i][t] & toLeft[k][j][t] & toLeft[i][k][t])
						{
							--res;
							break;
						}
					}
				}
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <iostream>
#include <vector>

using namespace std;

struct Point
{
	long long x, y;
	Point (long long x = 0, long long y = 0) : x(x), y(y) {}
	Point operator-(Point op) {
		return Point(x - op.x, y - op.y);
	}
	long long operator % (Point op) {
		return x * op.y - y * op.x;
	}
};

int Sign(long long x)
{
	return x < 0 ? -1 : x > 0 ? 1 : 0;
}

istream &operator >> (istream &in, Point &v) {
	in >> v.x >> v.y;
}

template<class T>
istream &operator >> (istream &in, vector<T> &v) {
	for (int i = 0; i < v.size(); ++i) {
		in >> v[i];
	}
}

int main() {
	int n, m;
	cin >> n >> m;

	vector<Point> red(n);
	cin >> red;

	vector<Point> blue(m);
	cin >> blue;

	vector< vector<int> > balance(n, vector<int>(n, 0));
	for (int i = 0; i < red.size(); ++i) {
		for (int j = 0; j < red.size(); ++j) {
			if (red[i].x != red[j].x) {
				int x1 = min(red[i].x, red[j].x);
				int x2 = max(red[i].x, red[j].x);
				for (int k = 0; k < blue.size(); ++k) {
					if (x1 <= blue[k].x && blue[k].x < x2) {
						balance[i][j] += Sign((blue[k] - red[i]) % (red[j] - red[i]));
					}
				}
			}
		}
	}

	int res = 0;
	for (int i = 0; i < red.size(); ++i) {
		for (int j = i + 1; j < red.size(); ++j) {
			for (int k = j + 1; k < red.size(); ++k) {
				res += balance[i][j] + balance[j][k] + balance[k][i] == 0;
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <algorithm>
#include <sstream>
#include <iostream>
using namespace std;

#define FOR(i,a,b) for(int i=(a); i<(int)(b); ++i)
#define sqr(a) ((a)*(a))
typedef long long i64;
typedef unsigned long long u64;

struct Point
{
	long long x, y;
	Point (long long xx = 0, long long yy = 0)
	{
		x = xx;
		y = yy;
	}
	Point operator - (const Point &op)  const
	{
		return Point(x - op.x, y - op.y);
	}
	long long operator % (const Point &op) const
	{
		return x * op.y - y * op.x;
	}
};

int toLeft[500][500][16];

void SetBit(int i, int j, int k)
{
	toLeft[i][j][k / 32] |= 1 << (k % 32);
}

bool ToLeft(Point &a, Point &b, Point &c)
{
	return (b - a) % (c - a) > 0;
}

void Copy(int a[], int b[])
{
	memcpy(a, b, sizeof(int) * 16);
}

void And(int a[], int b[])
{
	for (int i = 0; i < 16; ++i)
		a[i] &= b[i];
}

bool IsZero(int a[])
{
	for (int i = 0; i < 16; ++i)
		if (a[i]) return false;
	return true;
}

int main()
{
	int n, m;
	cin >> n >> m;

	vector<Point> a(n);
	for (int i = 0; i < n; ++i)
	{
		cin >> a[i].x >> a[i].y;
	}

	vector<Point> b(m);
	for (int i = 0; i < m; ++i)
	{
		cin >> b[i].x >> b[i].y;
	}

	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			Point aij = a[j] - a[i];
			for (int k = 0; k < m; ++k)
			{
				if ((aij % (b[k] - a[i])) > 0)
				{
					SetBit(i, j, k);
				}
			}
		}
	}

	int res = 0;

	int cur[16];

	for (int i = 0; i < n; ++i)
	{
		for (int j = i + 1; j < n; ++j)
		{
			for (int k = j + 1; k < n; ++k)
			{
				if (ToLeft(a[i], a[j], a[k]))
				{
					Copy(cur, toLeft[i][j]);
					And(cur, toLeft[j][k]);
					And(cur, toLeft[k][i]);
				}
				else
				{
					Copy(cur, toLeft[j][i]);
					And(cur, toLeft[k][j]);
					And(cur, toLeft[i][k]);
				}
				res += IsZero(cur);
			}
		}
	}

	cout << res << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

inline ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	ios::sync_with_stdio(0);

	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		cin >> a[i].st >> a[i].nd;

	for (int i = 1; i <= m; i++)
		cin >> b[i].st >> b[i].nd;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

inline ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%lld %lld", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%lld %lld", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (b[k].nd <= a[j].nd && a[i].nd < b[k].nd && ccw(a[i], a[j], b[k]) >= 0)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (b[k].nd <= a[i].nd && a[j].nd < b[k].nd && ccw(a[i], a[j], b[k]) <= 0)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%lld %lld", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%lld %lld", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%lld %lld", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%lld %lld", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				ans += cnt[i][j] + cnt[j][k] + cnt[k][i] == 0;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

inline ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		cin >> a[i].st >> a[i].nd;

	for (int i = 1; i <= m; i++)
		cin >> b[i].st >> b[i].nd;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%lld %lld", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%lld %lld", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				ans += !(cnt[i][j] + cnt[j][k] + cnt[k][i]);
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%d %d", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%d %d", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	printf("%d\n", ans);

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%d %d", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%d %d", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pll a[N+5], b[N+5];

inline ll ccw(pll a, pll b, pll c) {
	return (c.st - a.st) * (b.nd - a.nd) - (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%lld %lld", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%lld %lld", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) >= 0 && b[k].nd <= a[j].nd && a[i].nd < b[k].nd)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (ccw(a[i], a[j], b[k]) <= 0 && b[k].nd <= a[i].nd && a[j].nd < b[k].nd)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <bits/stdc++.h>

#define mp make_pair
#define st first
#define nd second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair< ll,ll > pll;
typedef pair< int,int > pii;

const int inf = 1000000000, N = 500;

int n, m, cnt[N+5][N+5];
pii a[N+5], b[N+5];

inline ll ccw(pii a, pii b, pii c) {
	return (ll) (c.st - a.st) * (b.nd - a.nd) - (ll) (b.st - a.st) * (c.nd - a.nd);
}

int main()
{
	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%d %d", &a[i].st, &a[i].nd);

	for (int i = 1; i <= m; i++)
		scanf("%d %d", &b[i].st, &b[i].nd);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (a[i].nd < a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (b[k].nd <= a[j].nd && a[i].nd < b[k].nd && ccw(a[i], a[j], b[k]) >= 0)
						cnt[i][j]++;
				}
			}
			else if (a[i].nd > a[j].nd) {
				for (int k = 1; k <= m; k++) {
					if (b[k].nd <= a[i].nd && a[j].nd < b[k].nd && ccw(a[i], a[j], b[k]) <= 0)
						cnt[i][j]--;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = i+1; j <= n; j++) {
			for (int k = j+1; k <= n; k++) {
				if (!(cnt[i][j] + cnt[j][k] + cnt[k][i]))
					ans++;
			}
		}
	}

	cout << ans << endl;

	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <climits>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <cassert>
#include <vector>
#define all(x) x.begin() , x.end()
#define fi first
#define se second
#define pb push_back
#define umax( x , y ) x = max( x , (y) )
#define umin( x , y ) x = min( x , (y) )
#define For( i , a ) for(int i=1;i<=a;i++)
#define ort (b+s)/2
#define y2 asrwjaelkf
#define pa() printf("asdasd\n")
#define y1 asseopirwjaelkf

using namespace std;

const int maxn = 100020;
const int maxx = 10000;
const int mod = 1e9+7;
const int K = 750;

typedef long long Lint;
typedef double db;
typedef pair<int,int> ii;
typedef pair<int,ii> iii;

struct point {
	int x, y, tp;
	db deg;
	friend bool operator < ( const point &a, const point &b ) { return (a.y == b.y)? (a.x < b.x) : (a.y < b.y); }
}ar[maxn];

int a, b;

bool comp( const point &a, const point &b ) {
	return a.deg < b.deg;
}

int main() {

	scanf("%d %d",&a,&b);

	for(int i=1,j,k;i<=a;i++) {
		scanf("%d %d",&ar[i].x,&ar[i].y);
		//~ printf("asdasd %d %d\n",ar[i].x,ar[i].y);
		ar[i].tp = 1;
	}
	for(int i=1;i<=b;i++)
		scanf("%d %d",&ar[a+i].x,&ar[a+i].y);

	a += b;
	int ans = 0;
	sort( ar+1, ar+1+a );

	//~ for(int i=1;i<=a;i++)
		//~ printf("asdasdasd %d --> %d %d \n",i,ar[i].x,ar[i].y);

	db e = 0.000001;

	for(int i=1;i<=a;i++) {
		if( !ar[i].tp ) continue;
		//~ printf("%d %d  %d--> %d\n",ar[i].x,ar[i].y,ar[i].tp,ans);
		vector <point> v(a-i);

		for(int j=0;j+i+1<=a;j++) {
			v[j] = ar[j+i+1];
			v[j].deg = atan2( v[j].y-ar[i].y, v[j].x-ar[i].x );
			//~ printf("%d %d --- %lf\n",v[j].x,v[j].y,v[j].deg);
		}

		sort( all( v ), comp );
		for(int j=0;j<v.size();j++) {
			if( !v[j].tp ) continue;
			db maxi = -1e9;
			for(int k=j+1;k<v.size();k++) {
				//~ printf("asdasdasd %d %d - (%lf) - %d %d %d\n",v[j].x,v[j].y,maxi,v[k].x,v[k].y,ans);
				db t = atan2( v[k].y-v[j].y, v[k].x-v[j].x );
				if( v[k].tp ) {
					if( t > maxi ) ans ++;
				} else umax( maxi, t );
			}
		}
		//~ printf("%d %d --> %d\n",ar[i].x,ar[i].y,ans);
		//~ printf("Came!\n");
	}
	cout << ans << endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <climits>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <cassert>
#include <vector>
#define all(x) x.begin() , x.end()
#define fi first
#define se second
#define pb push_back
#define umax( x , y ) x = max( x , (y) )
#define umin( x , y ) x = min( x , (y) )
#define For( i , a ) for(int i=1;i<=a;i++)
#define ort (b+s)/2
#define y2 asrwjaelkf
#define pa() printf("asdasd\n")
#define y1 asseopirwjaelkf

using namespace std;

const int maxn = 100020;
const int maxx = 10000;
const int mod = 1e9+7;
const int K = 750;

typedef long long Lint;
typedef double db;
typedef pair<int,int> ii;
typedef pair<int,ii> iii;

struct point {
	int x, y, tp;
	db deg;
	friend bool operator < ( const point &a, const point &b ) { return (a.y == b.y)? (a.x < b.x) : (a.y < b.y); }
}ar[maxn];

int a, b;

bool comp( const point &a, const point &b ) {
	return a.deg < b.deg;
}

int main() {

	scanf("%d %d",&a,&b);

	for(int i=1,j,k;i<=a;i++) {
		scanf("%d %d",&ar[i].x,&ar[i].y);
		//~ printf("asdasd %d %d\n",ar[i].x,ar[i].y);
		ar[i].tp = 1;
	}
	for(int i=1;i<=b;i++)
		scanf("%d %d",&ar[a+i].x,&ar[a+i].y);

	a += b;
	int ans = 0;
	sort( ar+1, ar+1+a );

	//~ for(int i=1;i<=a;i++)
		//~ printf("asdasdasd %d --> %d %d \n",i,ar[i].x,ar[i].y);

	db e = 0.000001;

	for(int i=1;i<=a;i++) {
		if( !ar[i].tp ) continue;
		//~ printf("%d %d  %d--> %d\n",ar[i].x,ar[i].y,ar[i].tp,ans);
		vector <point> v(a-i);

		for(int j=0;j+i+1<=a;j++) {
			v[j] = ar[j+i+1];
			v[j].deg = atan2( v[j].y-ar[i].y, v[j].x-ar[i].x );
			//~ printf("%d %d --- %lf\n",v[j].x,v[j].y,v[j].deg);
		}

		sort( all( v ), comp );
		for(int j=0;j<v.size();j++) {
			if( !v[j].tp ) continue;
			db maxi = -1e9;
			for(int k=j+1;k<v.size();k++) {
				//~ printf("asdasdasd %d %d - (%lf) - %d %d %d\n",v[j].x,v[j].y,maxi,v[k].x,v[k].y,ans);
				db t = atan2( v[k].y-v[j].y, v[k].x-v[j].x );
				if( t < 0 ) t += 10;
				if( v[k].tp ) {
					if( t > maxi ) ans ++;
				} else umax( maxi, t );
			}
		}
		//~ printf("%d %d --> %d\n",ar[i].x,ar[i].y,ans);
		//~ printf("Came!\n");
	}
	cout << ans << endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <climits>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <cassert>
#include <vector>
#define all(x) x.begin() , x.end()
#define fi first
#define se second
#define pb push_back
#define umax( x , y ) x = max( x , (y) )
#define umin( x , y ) x = min( x , (y) )
#define For( i , a ) for(int i=1;i<=a;i++)
#define ort (b+s)/2
#define y2 asrwjaelkf
#define pa() printf("asdasd\n")
#define y1 asseopirwjaelkf

using namespace std;

const int maxn = 1020;
const int maxx = 10000;
const int mod = 1e9+7;
const int K = 750;

typedef long long Lint;
typedef double db;
typedef pair<int,int> ii;
typedef pair<int,ii> iii;

struct point {
	int x, y, tp;
	db deg;
	friend bool operator < ( const point &a, const point &b ) { return (a.y == b.y)? (a.x < b.x) : (a.y < b.y); }
}ar[maxn];

int a, b;
db ang[maxn][maxn];
int now;

bool comp( const int &a, const int &b ) {
	return ang[now][a] < ang[now][b];
}

int main() {

	scanf("%d %d",&a,&b);

	for(int i=1,j,k;i<=a;i++) {
		scanf("%d %d",&ar[i].x,&ar[i].y);
		//~ printf("asdasd %d %d\n",ar[i].x,ar[i].y);
		ar[i].tp = 1;
	}
	for(int i=1;i<=b;i++)
		scanf("%d %d",&ar[a+i].x,&ar[a+i].y);

	a += b;
	int ans = 0;
	sort( ar+1, ar+1+a );

	for(int i=1;i<=a;i++)
		for(int j=1;j<=a;j++)
			if( i != j ) ang[i][j] = atan2( ar[j].y-ar[i].y, ar[j].x-ar[i].x );

	for(int i=1;i<=a;i++) {
		if( !ar[i].tp ) continue;
		vector <int> v(a-i);

		for(int j=0;j+i+1<=a;j++)
			v[j] = j+i+1;

		now = i;
		sort( all( v ), comp );
		for(int j=0;j<v.size();j++) {
			if( !ar[v[j]].tp ) continue;
			db maxi = -1e9;
			for(int k=j+1;k<v.size();k++) {
				db t = ang[v[j]][v[k]];
				if( t < 0 ) t += 10;
				if( ar[v[k]].tp ) {
					if( t > maxi ) ans ++;
				} else umax( maxi, t );
			}
		}
	}
	cout << ans << endl;
	return 0;
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace ArchiveApps
{
    class Program_785A
    {
        static void Main(string[] args)
        {
            var figuresNum = Int32.Parse(Console.ReadLine());

            int totalVertexes = 0;
            for (int i = 0; i < figuresNum; i++)
            {
                string name = Console.ReadLine();

                switch (name)
                {
                    case "Tetrahedron":
                        totalVertexes += 4;
                        break;
                    case "Cube":
                        totalVertexes += 6;
                        break;
                    case "Octahedron":
                        totalVertexes += 8;
                        break;
                    case "Dodecahedron":
                        totalVertexes += 12;
                        break;
                    case "Icosahedron":
                        totalVertexes += 20;
                        break;
                }
            }

            Console.WriteLine(totalVertexes);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AntonAndPolyhedrons
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = Convert.ToInt32(Console.ReadLine());
            string[] str = new String[n];
            for (int i = 0; i < n; i++)
            {
                str[i] = Console.ReadLine();
            }
            int count = 0;
            for (int i = 0; i < n; i++)
            {
                if (str[i] == "Tetrahedron")
                {
                    count += 4;
                }
                if (str[i] == "Cube")
                {
                    count += 6;
                }
                if (str[i] == "Octahedron")
                {
                    count += 8;
                }
                if (str[i] == "Dodecahedron")
                {
                    count += 12;
                }
                if (str[i] == "Icosahedron")
                {
                    count +=20;
                }
            }

            Console.WriteLine(count);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Anton_and_Polyhedrons
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine());
            int f = 0;
            for (int i = 0; i < n; i++)
            {
                string polyhedrons = Console.ReadLine();
                if(string.Compare(polyhedrons,"Tetrahedron")==0)
                {
                    f+=4;
                }
                else if(string.Compare(polyhedrons,"Cube")==0)
                {
                    f += 6;
                }
                else if (string.Compare(polyhedrons, "Octahedron") == 0)
                {
                    f += 8;
                }
                else if (string.Compare(polyhedrons, "Dodecahedron") == 0)
                {
                    f += 12;
                }
                else
                {
                    f += 20;
                }
            }
            Console.WriteLine(f);
        }
    }
}


using System;
using System.IO;
using System.Text;

namespace Anton_and_Polyhedrons
{
    internal class Program
    {
        private static readonly StreamReader reader = new StreamReader(Console.OpenStandardInput(1024*10), Encoding.ASCII, false, 1024*10);
        private static readonly StreamWriter writer = new StreamWriter(Console.OpenStandardOutput(1024*10), Encoding.ASCII, 1024*10);

        private static void Main(string[] args)
        {
            int n = int.Parse(reader.ReadLine());

            int sum = 0;
            for (int i = 0; i < n; i++)
            {
                string s = reader.ReadLine();

                switch (s[0])
                {
                    case 'T':
                        sum += 4;
                        break;
                    case 'C':
                        sum += 6;
                        break;
                    case 'O':
                        sum += 8;
                        break;
                    case 'D':
                        sum += 12;
                        break;
                    case 'I':
                        sum += 20;
                        break;
                }
            }

            writer.WriteLine(sum);
            writer.Flush();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AntonandPolyhedrons
{
    class Program
    {

        static void Main(string[] args)
        {
            var l = new Dictionary<string, int>();
            l["Tetrahedron"] = 4;
            l["Cube"] = 6;
            l["Octahedron"] = 8;
            l["Dodecahedron"] = 12;
            l["Icosahedron"] = 20;
            int n = Int32.Parse(Console.ReadLine());
            int count = 0;
            for (int i = 0; i < n; i++)
            {
                count += l[Console.ReadLine()];
            }
            Console.WriteLine(count);
            Console.ReadLine();
        }
    }
}


using System;

namespace _785A
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine());
            long sum = 0;
            for (int i = 0; i < n; i++)
            {
                string line = Console.ReadLine();
                switch (line)
                {
                    case "Tetrahedron":
                        sum += 4L;
                        break;
                    case "Cube":
                        sum += 6L;
                        break;
                    case "Octahedron":
                        sum += 8L;
                        break;
                    case "Dodecahedron":
                        sum += 12L;
                        break;
                    case "Icosahedron":
                        sum += 20L;
                        break;
                }
            }
            Console.WriteLine(sum);
        }
    }
}