#include <fstream>
#include <algorithm>
using namespace std;
int const maxz=60000;
int const maxn=800;
struct Edge{int x1,x2,y1,y2;};
int Z[maxn][2],X[2+maxn],N,K;Edge S[2+maxn][2+maxn];int L[2+maxn];
long long int crp(const Edge & e,int x,int y)
{ long long int x1=e.x2-e.x1,y1=e.y2-e.y1,x2=x-e.x1,y2=y-e.y1,p=x1*y2-x2*y1;
return p;
}
bool operator<(const Edge&a,const Edge&b)
{ long long int q;
if((a.x1<=b.x1)&&(b.x1<=a.x2))
{ q=crp(a,b.x1,b.y1);
if(0==q){q=crp(a,b.x2,b.y2);}
return 0<q;
}
if((a.x1<=b.x2)&&(b.x2<=a.x2))
{ q=crp(a,b.x2,b.y2);
if(0==q){q=crp(a,b.x1,b.y1);}
return 0<q;
}
q=crp(b,a.x1,a.y1);
if(0==q){q=crp(b,a.x2,a.y2);}
return 0>q;
}
void add_strips()
{ int i,j;
X[0]=-1;for(i=0;N>i;++i){X[1+i]=Z[i][0];}X[1+N]=maxz+1;
sort(X,X+N+2);
for(i=1,j=0;N+2>i;++i)
{if(X[j]!=X[i]){++j;if(j!=i){X[j]=X[i];}}}K=j;
}
void add_edges()
{ int i,j;
for(j=0;K>j;++j)
{ L[j]=0;Edge e={-1,1+maxz,-1,-1};S[j][L[j]++]=e;
for(i=0;N>i;++i)
{ int x1=Z[i][0],y1=Z[i][1],x2=Z[(1+i)%N][0],y2=Z[(1+i)%N][1],t;
if(x1>x2){t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t;}
if((x1<x2)&&(x1<=X[j])&&(X[1+j]<=x2))
{Edge e={x1,x2,y1,y2};S[j][L[j]++]=e;}
}
sort(&S[j][0],&S[j][L[j]]);
Edge f={-1,1+maxz,1+maxz,1+maxz};S[j][L[j]++]=f;
}
}
bool inside(int i,int x,int y)
{ int a=0,b=L[i]-1,m;
long long int q;
while(a+1<b)
{ m=(a+b)/2;q=crp(S[i][m],x,y);
if(0==q){return true;}
if(0>q){b=m;}else{a=m;}
}
int s=((L[i]-1-a)-1);
return (1==(s%2));
}
bool inside(int x, int y)
{ int a=0,b=K,m,i;
while(a+1<b){m=((a+b)/2);if(x<=X[m]){b=m;}else{a=m;}}
i=b-1;if(inside(i,x,y)){return true;}
++i;if((K>i)&&(X[i]==x)&&inside(i,x,y)){return true;}
return false;
}
int main()
{ ifstream is("poligon.in");int m;
is>>N>>m;int i,s,x,y;
for(i=0;N>i;++i){is>>Z[i][0]>>Z[i][1];}
add_strips();
add_edges();
for(s=0;0<m;--m)
{ is>>x>>y;
if(inside(x,y)){++s;}
}
ofstream os("poligon.out");
os<<s<<endl;
return 0;
}