#include <algorithm>
#include <bitset>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

#define rep(i, n) for (int64_t i = 0; i < (n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)

class Vec;
Vec operator/(const Vec& v, const double& divisor);
Vec operator*(const double& scale, const Vec& v);

class Vec {
  using F = double;
  vector<F> container;

 public:
  Vec(size_t size) : container(size) {}
  Vec(initializer_list<F> elements)
      : container(elements.begin(), elements.end()) {}
  size_t dim() const { return container.size(); }
  F& operator[](const size_t size) { return container.at(size); }
  const F& operator[](const size_t size) const { return container.at(size); }
  Vec operator+(const Vec& other) const {
    Vec ret(*this);
    for (size_t i = 0; i < dim(); i++) ret[i] += other[i];
    return ret;
  }
  Vec operator-(const Vec& other) const { return (*this) + (-other); }
  Vec operator-() const { return -1.0 * (*this); }
  F inner(const Vec& other) const {
    F acc = 0;
    for (size_t i = 0; i < dim(); i++) {
      acc += (*this)[i] * other[i];
    }
    return acc;
  }
  F norm() const { return sqrt(inner(*this)); }
  Vec unit() const { return (*this) / this->norm(); }
  F ccw(const Vec& other) const {
    return (*this)[0] * other[1] - other[0] * (*this)[1];
  }
  Vec normal() const { return Vec({-(*this)[1], (*this)[0]}); }
};
Vec operator/(const Vec& v, const double& divisor) { return 1.0 / divisor * v; }
Vec operator*(const double& scale, const Vec& v) {
  Vec ret(v);
  for (size_t i = 0; i < ret.dim(); i++) ret[i] *= scale;
  return ret;
}

class Segment {
  const Vec m_start;
  const Vec m_end;

 public:
  Segment(const Vec& start, const Vec& end) : m_start(start), m_end(end) {}
  static const int ONLINE = 0x7;
  static const int ONSEGMENT = 0x1;
  static const int FRONT = 0x2;
  static const int BACK = 0x4;
  static const int OFFLINE = 0x18;
  static const int CCW = 0x8;
  static const int CW = 0x10;
  int check_rel(const Vec& p, double eps) const {
    const Vec u = direction();
    const Vec v = p - m_start;
    const double uLen = u.norm();

    const double a = u.ccw(v);

    int result = 0;
    if (a > eps) {
      result |= CCW;
    } else if (a < -eps) {
      result |= CW;
    } else {
      const double det = u.inner(v) / uLen;
      if (det < -eps) {
        result |= BACK;
      } else if (det > uLen + eps) {
        result |= FRONT;
      } else {
        result |= ONSEGMENT;
      }
    }
    return result;
  }
  bool intersect(const Segment& other, const double eps) const {
    const Vec u = other.m_start - m_start, w = other.m_end - m_start;
    const Vec v0 = m_end - m_start, v1 = other.m_end - other.m_start;

    const double vn = v0.norm();
    double u_v = v0.inner(u) / vn;
    double w_v = v0.inner(w) / vn;
    if (abs(abs(u_v / u.norm()) - 1) < eps &&
        abs(abs(w_v / w.norm()) - 1) < eps) {
      if (u_v > w_v) {
        swap(u_v, w_v);
      }
      return !(u_v > vn + eps || w_v < -eps);
    }
    bool cond1 =
        v0.ccw(other.m_start - m_start) * v0.ccw(other.m_end - m_start) < eps;
    bool cond2 =
        v1.ccw(m_start - other.m_start) * v1.ccw(m_end - other.m_start) < eps;
    return cond1 && cond2;
  }
  Vec direction() const { return m_end - m_start; }
  double dist(const Vec& p) const {
    const Vec dir = direction();
    const Vec d = dir.unit();
    const Vec q = p - m_start;
    const double a = d.inner(q);
    if (a < 0) {
      return (m_start - p).norm();
    } else if (dir.norm() < a) {
      return (m_end - p).norm();
    } else {
      return abs(d.normal().inner(q));
    }
  }
  double dist(const Segment& other) const {
    if (intersect(other, 0.0)) {
      return 0.0;
    }
    return min(min(dist(other.m_start), dist(other.m_end)),
               min(other.dist(m_start), other.dist(m_end)));
  }
};

class Polygon {
  const vector<Vec>& vert;

 public:
  Polygon(const vector<Vec>& vert) : vert(vert) {}
  double area() const {
    const size_t n = vert.size();
    double acc = 0;
    for (size_t i = 0; i < n; i++) {
      acc += vert[i].ccw(vert[(i + 1) % n]);
    }
    return acc / 2.0;
  }
  bool isConvex(double eps) const {
    const size_t n = vert.size();
    for (size_t i = 0; i < n; i++) {
      const Vec a = vert[(i + 1) % n] - vert[i],
                b = vert[(i + 2) % n] - vert[i];
      const double c = a.ccw(b);
      if (c < -eps) {
        return false;
      }
    }
    return true;
  }

  static const int ON_EDGE = 0x3;
  static const int CONTAINED = 0x1;
  static const int NOT_CONTAINED = 0x2;
  int check_rel(const Vec& p, double eps) const {
    const size_t n = vert.size();
    double angle = 0;
    for (size_t i = 0; i < n; i++) {
      const Vec &s = vert[i], &t = vert[(i + 1) % n];

      if (Segment(s, t).check_rel(p, eps) == Segment::ONSEGMENT) {
        return ON_EDGE;
      }

      const Vec u = s - p, v = t - p;
      const double theta = atan2(u.ccw(v), u.inner(v));
      angle += theta;
    }
    if (angle < 3) {  // check if 0 or 2*PI
      return NOT_CONTAINED;
    } else {
      return CONTAINED;
    }
  }
};

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

  vector<Vec> v;
  rep(i, n) {
    double x, y;
    cin >> x >> y;
    v.push_back(Vec({x, y}));
  }

  int q;
  cin >> q;
  rep(i, q) {
    double x, y;
    cin >> x >> y;
    Vec p({x, y});

    const double EPS = 1e-9;
    int result = Polygon(v).check_rel(p, EPS);
    if (result == Polygon::ON_EDGE) {
      cout << 1 << endl;
    } else if (result == Polygon::CONTAINED) {
      cout << 2 << endl;
    } else {
      cout << 0 << endl;
    }
  }

  return 0;
}



Measured memory_bytes: 3532