/* template.cpp {{{ */
#include <bits/stdc++.h>
using namespace std;
 
// #define int long long
#define GET_MACRO(a, b, c, d, NAME, ...) NAME
#define REP1(n) REP2(i_, n)
#define REP2(i, n) REP3(i, 0, n)
#define REP3(i, a, b) REP4(i, a, b, 1)
#define REP4(i, a, b, s) for (long long i = (a); i < (long long)(b); i += (long long)(s))
#define RREP1(n) RREP2(i_, n)
#define RREP2(i, n) RREP3(i, 0, n)
#define RREP3(i, a, b) RREP4(i, a, b, 1)
#define RREP4(i, a, b, s) for (long long i = (b) - 1; i >= (long long)(a);  i -= (long long)(s))
#define rep(...) GET_MACRO(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define rrep(...) GET_MACRO(__VA_ARGS__, RREP4, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define fs first
#define sc second
#define all(c) std::begin(c), std::end(c)
#define rall(c) (c).begin(), (c).end()
#define pcnt(x) __builtin_popcountll(x)
#define each(x, c) for (auto &&x : c)
#define endl "\n"
#define y0 y0_
#define y1 y1_
#define yn yn_
#define left left_
#define right right_
 
#define TMP_T template<typename T>
#define TMP_TU template<typename T, typename U>
#define TMP_Ts template<typename ...T>
#define TMP_NTs template<size_t N, typename ...T>
#define TMP_CT template<bool C, typename T = void>
 
#ifndef DEBUG
#define cerr no_output
struct NoOutput : ostream {
  TMP_T ostream &operator<<(const T &){ return *this; }
} no_output;
#endif
 
using uint = unsigned;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
TMP_T using PQL = priority_queue<T, vector<T>, greater<T>>;
TMP_T using PQG = priority_queue<T>;
TMP_CT using enable_if_t = typename enable_if<C, T>::type;
 
const ll LLINF = 1e18 + 10;
#ifndef int
const int INF = 1e9 + 10;
#else
const int INF = LLINF;
#endif
 
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, -1, 0, 1, -1, -1, 1, 1};
 
TMP_T inline constexpr T sq(T x){ return x * x; }
TMP_TU inline T& chmin(T &x, U y){ if (x > y) x = y; return x; }
TMP_TU inline T& chmax(T &x, U y){ if (x < y) x = y; return x; }
 
TMP_NTs enable_if_t<(N >= sizeof...(T))> input_tuple(istream &, tuple<T...> &){}
TMP_NTs enable_if_t<(N < sizeof...(T))> input_tuple(istream &is, tuple<T...> &x){ is >> get<N>(x); input_tuple<N + 1, T...>(is, x); }
TMP_Ts ostream &operator>>(istream &is, tuple<T...> &x){ input_tuple<0, T...>(is, x); return is; }
TMP_TU ostream &operator>>(istream &is, pair<T, U> &x){ return is >> x.first >> x.second; }
TMP_NTs enable_if_t<(N >= sizeof...(T))> print_tuple(ostream &, const tuple<T...> &){}
TMP_NTs enable_if_t<(N < sizeof...(T))> print_tuple(ostream &os, const tuple<T...> &x){ os << (N > 0 ? " " : "") << get<N>(x); print_tuple<N + 1, T...>(os, x); }
TMP_Ts ostream &operator<<(ostream &os, const tuple<T...> &x){ print_tuple<0, T...>(os, x); return os; }
TMP_TU ostream &operator<<(ostream &os, const pair<T, U> &x){ return os << x.first << " " << x.second; }
TMP_T vector<T> reversed(const vector<T> &c){ auto d = c; reverse(all(d)); return d; }
string reversed(const string &s){ auto t = s; reverse(all(t)); return t; }
TMP_T void unique(vector<T> &c){ sort(all(c)); c.erase(unique(all(c)), end(c)); }
TMP_T vector<T> uniqued(const vector<T> &c){ auto d = c; unique(d); return d; }

#undef TMP_T
#undef TMP_TU
#undef TMP_Ts
#undef TMP_NTs
#undef TMP_CT

ll gcd(ll a, ll b){ return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b){ return a / gcd(a, b) * b; }
tuple<ll, ll, ll> extgcd(ll a, ll b){
  if (b){
    ll g, x, y;
    tie(g, x, y) = extgcd(b, a % b);
    return make_tuple(g, y, x - a / b * y);
  }
  return make_tuple(a, 1, 0);
}
ll invmod(ll a, ll m = 1000000007){
  ll g, x;
  tie(g, x, ignore) = extgcd(a, m);
  return g == 1 ? (x + m) % m : 0;
}

inline ll in(){ ll x; cin >> x; return x; }
 
struct prepare {
  prepare(){
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(12);
    cerr << fixed << setprecision(12);
#ifndef DEBUG
    cin.tie(nullptr);
#endif
  }
} prepare_;
/* }}} */
/* geometry.cpp {{{ */
/* object {{{ */
using Real = long double;
using Point = complex<Real>;

struct Line {
  Point p, q;
  Line(){}
  Line(const Point &p, const Point &q): p(p), q(q){}
};

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

using Segment = Line;
using Polygon = vector<Point>;

int sgn(Real, Real);
namespace std {
  bool operator<(const Point &a, const Point &b){
    return sgn(real(a), real(b)) ? sgn(real(a), real(b)) < 0 : sgn(imag(a), imag(b)) < 0;
  }
  bool operator==(const Point &a, const Point &b){
    return sgn(real(a), real(b)) == 0 && sgn(imag(a), imag(b)) == 0;
  }
}
/* }}} */
/* const {{{ */
const Real EPS = 1e-8l;
const Real PI = acos(-1.0l);
/* }}} */
/* compare {{{ */
int sgn(Real x){
  return (x > EPS) - (x < -EPS);
}

int sgn(Real x, Real y){
  return sgn(x - y);
}
/* }}} */
/* input {{{ */
istream &operator>>(istream &is, Point &p){
  Real x, y;
  is >> x >> y;
  p.real(x), p.imag(y);
  return is;
}

istream &operator>>(istream &is, Line &l){
  return is >> l.p >> l.q;
}

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

istream &operator>>(istream &is, Polygon &g){
  each(p, g) is >> p;
  return is;
}
/* }}} */
/* output {{{ */
ostream &operator<<(ostream &os, const Point &p){
  return os << p.real() << " " << p.imag();
}

ostream &operator<<(ostream &os, const Line &l){
  return os << l.p << " " << l.q;
}

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

ostream &operator<<(ostream &os, const Polygon &g){
  for (int i = 0; i < (int)g.size(); i++){
    os << g[i];
    if (i + 1 < (int)g.size()) os << endl;
  }
  return os;
}
/* }}} */
/* dot, cross {{{ */
Real dot(const Point &a, const Point &b){
  return real(conj(a) * b);
}

Real cross(const Point &a, const Point &b){
  return imag(conj(a) * b);
}
/* }}} */
/* ccw {{{ */
int ccw(const Point &a, const Point &b, const Point &c){
  Point u = b - a, v = c - a;
  if (sgn(cross(u, v)) > 0) return 1;
  if (sgn(cross(u, v)) < 0) return -1;
  if (sgn(dot(u, v)) < 0) return 2;
  if (sgn(norm(u), norm(v)) < 0) return -2;
  return 0;
}
/* }}} */
/* orthogonal, parallel {{{ */
bool orthogonal(const Line &l, const Line &m){
  return sgn(dot(l.q - l.p, m.q - m.p)) == 0;
}

bool parallel(const Line &l, const Line &m){
  return sgn(cross(l.q - l.p, m.q - m.p)) == 0;
}
/* }}} */
/* intersect {{{ */
bool intersectLL(const Line &l, const Line &m){
  return !parallel(l, m) ? true : parallel(l, Line(l.p, m.p));
}

bool intersectLS(const Line &l, const Segment &s){
  return sgn(cross(l.q - l.p, s.p - l.p)) * sgn(cross(l.p - l.p, s.q - l.p)) <= 0;
}

bool intersectLP(const Line &l, const Point &p){
  return ~ccw(l.p, l.q, p) & 1;
}

bool intersectSS(const Segment &s, const Segment &t){
  return ccw(s.p, s.q, t.p) * ccw(s.p, s.q, t.q) <= 0
      && ccw(t.p, t.q, s.p) * ccw(t.p, t.q, s.q) <= 0;
}

bool intersectSP(const Segment &s, const Point &p){
  return !ccw(s.p, s.q, p);
}
/* }}} */
/* project, refrect {{{ */
Point project(const Line &l, const Point &p){
  Real t = dot(p - l.p, l.p - l.q) / norm(l.p - l.q);
  return l.p + t * (l.p - l.q);
}

Point reflect(const Line &l, const Point &p){
  return p + 2.0l * (project(l, p) - p);
}
/* }}} */
/* distance {{{ */
Real distanceLP(const Line &l, const Point &p){
  return abs(p - project(l, p));
}

Real distanceLL(const Line &l, const Line &m){
  return intersectLL(l, m) ? 0.0l : distanceLP(l, m.p);
}

Real distanceLS(const Line &l, const Segment &s){
  if (intersectLS(l, s)) return 0.0l;
  return min(distanceLP(l, s.p), distanceLP(l, s.q));
}

Real distanceSP(const Segment &s, const Point &p){
  if (sgn(dot(s.q - s.p, p - s.p)) <= 0) return abs(s.p - p);
  if (sgn(dot(s.p - s.q, p - s.q)) <= 0) return abs(s.q - p);
  return distanceLP(s, p);
}

Real distanceSS(const Segment &s, const Segment &t){
  if (intersectSS(s, t)) return 0.0l;
  return min({
    distanceSP(s, t.p), distanceSP(s, t.q),
    distanceSP(t, s.p), distanceSP(t, s.q)
  });
}
/* }}} */
/* cross point {{{ */
Point crossPoint(const Line &l, const Line &m){
  Real a = cross(l.q - l.p, m.q - m.p);
  Real b = cross(l.q - l.p, l.q - m.p);
  if (sgn(a) == 0 && sgn(b) == 0) return m.p;
  if (sgn(a) == 0) assert(false);
  return m.p + b / a * (m.q - m.p);
}
/* }}} */
/* area {{{ */
Real area(const Polygon &g){
  Real s = 0.0l;
  for (int i = 0; i < (int)g.size(); i++){
    s += cross(g[i], g[(i + 1) % g.size()]);
  }
  return abs(s / 2.0l);
}
/* }}} */
int contains(const Polygon &g, const Point &p){
  int in = 0;
  rep(i, g.size()){
    Point a = g[i] - p, b = g[(i + 1) % g.size()] - p;
    if (imag(a) > imag(b)) swap(a, b);
    if (sgn(imag(a)) <= 0 && sgn(imag(b)) > 0){
      if (sgn(cross(a, b)) < 0) in ^= 1;
    }
    if (sgn(cross(a, b)) == 0 && sgn(dot(a, b)) <= 0) return 2;
  }
  return in;
}
/* }}} */

signed main()
{
  Polygon g(in());
  cin >> g;
  int q = in();
  rep(q){
    Point p;
    cin >> p;
    int t = contains(g, p);
    if (t) t = 3 - t;
    cout << t << endl;
  } 
}

Measured memory_bytes: 3292