Problem:
Polygon-Point-Containment

For a given polygon g and target points t, print "2" if g contains t, "1" if t is on a segment of g, "0" otherwise.

g is represented by a sequence of points p1, p2,..., pn where line segments connecting pi and pi+1 (1 ≤ i ≤ n-1) are sides of the polygon. The line segment connecting pn and p1 is also a side of the polygon.

Note that the polygon is not necessarily convex.

Input

The entire input looks like:

g (the sequence of the points of the polygon)
q (the number of queris = the number of target points)
1st query
2nd query
:
qth query

g is given by coordinates of the points p1,..., pn in the following format:

n
x1 y1
x2 y2
:
xn yn

The first integer n is the number of points. The coordinate of a point pi is given by two integers xi and yi. The coordinates of points are given in the order of counter-clockwise visit of them.

Each query consists of the coordinate of a target point t. The coordinate is given by two intgers x and y.

Output

For each query, print "2", "1" or "0".

Constraints

3 ≤ n ≤ 100

1 ≤ q ≤ 1000

-10000 ≤ xi, yi ≤ 10000

No point of the polygon will occur more than once.

Two sides of the polygon can intersect only at a common endpoint.

Sample Input

4
0 0
3 1
2 3
0 3
3
2 1
0 2
3 2

Sample Output

2
1
0

Solution in C# (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.IO;


namespace AOJ
{
    using Vector = Point;
    using Line = Segment;
    using Polygon = List<Point>;

    class Consts
    {
        public static readonly double EPS = 1e-10;
    }
    class Point
    {
        double x, y;
        public double X { get { return this.x; } set { this.x = value; } }
        public double Y { get { return this.y; } set { this.y = value; } }
        public Point(double x = 0, double y = 0)
        {
            this.x = x;
            this.y = y;
        }

        static public Point operator +(Point p1, Point p2) => new Point(p1.x + p2.x, p1.y + p2.y);
        static public Point operator -(Point p1, Point p2) => new Point(p1.x - p2.x, p1.y - p2.y);
        static public Point operator *(Point p, double a) => new Point(a * p.x, a * p.y);
        static public Point operator *(double a, Point p) => p * a;
        static public Point operator /(Point p, double a) => new Point(p.x / a, p.y / a);
        static public bool operator <(Point p1, Point p2) => p1.x != p2.x ? p1.x < p2.x : p1.y < p2.y;
        static public bool operator >(Point p1, Point p2) => p2 < p1;

        static public bool operator ==(Point p1, Point p2) => (p1.x - p2.x) < Consts.EPS && (p1.y - p2.y) < Consts.EPS;
        static public bool operator !=(Point p1, Point p2) => !(p1 == p2);

        public double abs() => Math.Sqrt(norm());
        public double norm() => this.x * this.x + this.y * this.y;

        public override bool Equals(object obj)
        {
            if ((object)obj == null || this.GetType() != obj.GetType())
            {
                return false;
            }
            var c = (Point)obj;
            return this == c;
        }
        public override int GetHashCode()
        {
            return this.x.GetHashCode() ^ this.y.GetHashCode();
        }
    }
    struct Segment
    {
        public Segment(Point p1,Point p2)
        {
            this.p1 = p1;
            this.p2 = p2;
        }
        public Point p1, p2;
    }
    class Circle
    {
        public Point c;
        public double r;
        public Circle(Point c, double r)
        {
            this.c = c;
            this.r = r;
        }
    }

    class VecCalc
    {
        static bool equals(double a, double b) => Math.Abs(a - b) < Consts.EPS;
        //内積
        static public double dot(Vector a, Vector b)
        {
            return a.X * b.X + a.Y * b.Y;
        }
        //外積
        static public double cross(Vector a, Vector b)
        {
            return a.X * b.Y - a.Y * b.X;
        }
        //16.2 直行判定
        static public bool isOrthogonal(Vector a, Vector b)
        {
            return equals(dot(a, b), 0.0);
        }
        static public bool isOrthogonal(Point a1, Point a2, Point b1, Point b2)
        {
            return isOrthogonal(a1 - a2, b1 - b2);
        }
        static public bool isOrthogonal(Segment s1, Segment s2)
        {
            return equals(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
        }
        //16.2 平行判定
        static public bool isParallel(Vector a, Vector b)
        {
            return equals(cross(a, b), 0.0);
        }
        static public bool isParallel(Point a1, Point a2, Point b1, Point b2)
        {
            return isParallel(a1 - a2, b1 - b2);
        }
        static public bool isParallel(Segment s1, Segment s2)
        {
            return equals(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
        }
        //16.3 射影
        static public Point project(Segment s, Point p)
        {
            Vector b = s.p2 - s.p1;
            double r = dot(p - s.p1, b) / b.norm();
            return s.p1 + b * r;
        }
        //16.4 反射
        static public Point reflection(Segment s, Point p)
        {
            return 2 * project(s, p) - p;
            //mid = project(s, p) - p;
            //return mid + mid - p;
        }
        //16.5 距離
        //2点間の距離
        static public double getDistance(Point a, Point b)
        {
            return (a - b).abs();
        }
        //直線lと点pの距離
        static public double getDistanceLP(Line l,Point p)
        {
            return Math.Abs(cross(l.p2 - l.p1, p - l.p1) / (l.p2 - l.p1).abs());
        }
        //線分sと点pの距離
        static public double getDistanceSP(Segment s, Point p)
        {
            if (dot(s.p2 - s.p1, p - s.p1) < 0.0) return (p - s.p1).abs();
            if (dot(s.p1 - s.p2, p - s.p2) < 0.0) return (p - s.p2).abs();
            return getDistanceLP(s, p);
        }
        static public double getDistance(Segment s1, Segment s2)
        {
            if (intersect(s1, s2)) return 0.0;
            return Math.Min(
                    Math.Min(getDistanceSP(s1, s2.p1), getDistanceSP(s1, s2.p2)),
                    Math.Min(getDistanceSP(s2, s1.p1), getDistanceSP(s2, s1.p2))
                );
        }
        //16.6 反時計回り
        static public readonly int COUNTER_CLOCKWISE=1;
        static public readonly int CLOCKWISE = -1;
        static public readonly int ONLINE_BACK = 2;
        static public readonly int ONLINE_FRONT = -2;
        static public readonly int ON_SEGMENT = 0;
        static public int ccw(Point p0, Point p1, Point p2)
        {
            Vector a = p1 - p0;
            Vector b = p2 - p0;
            var dot_ = dot(a, b);
            var cross_ = cross(a, b);
            if (Consts.EPS < cross_) return COUNTER_CLOCKWISE;
            if (cross_ < -Consts.EPS) return CLOCKWISE;
            if (dot_ < -Consts.EPS) return ONLINE_BACK;
            if (a.norm() < b.norm()) return ONLINE_FRONT;
            return ON_SEGMENT;
        }
        static public int ccw(Segment s, Point p)
        {
            return ccw(s.p1, s.p2, p);

        }
        //16.7 線分の交差判定
        static public bool intersect(Point p1, Point p2,Point p3,Point p4)
        {
            return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
                ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0
                );
        }
        static public bool intersect(Segment s1, Segment s2)
        {
            return intersect(s1.p1, s1.p2, s2.p1, s2.p2);
        }
        //16.8 線分の交点
        static public Point getCrossPoint(Segment s1, Segment s2)
        {
            Vector b = s2.p2 - s2.p1;
            double d1 = Math.Abs(cross(b, s1.p1 - s2.p1));
            double d2 = Math.Abs(cross(b, s1.p2 - s2.p1));
            double t = d1 / (d1 + d2);
            return s1.p1 + (s1.p2 - s1.p1) * t;
        }
        //16.9 円と直線の交点
        static public Segment getCrossPoints(Circle c, Line l)
        {
            Vector pr = project(l, c.c);
            System.Diagnostics.Debug.Assert((c.c - pr).abs() <= c.r);
            Vector e = (l.p2 - l.p1) / (l.p2 - l.p1).abs();
            double b = Math.Sqrt(c.r * c.r - (c.c - pr).norm());
            return new Segment(pr + e * b, pr - e * b);
        }
        //16.10 円と円の交点
        static double arg(Vector p) { return Math.Atan2(p.Y, p.X); }
        static Vector polar(double a, double r) { return new Point(Math.Cos(r) * a, Math.Sin(r) * a); }
        static public Segment getCrossPoints(Circle c1 , Circle c2)
        {
            double d = (c1.c - c2.c).abs();
            System.Diagnostics.Debug.Assert(d <= c1.r + c2.r);
            double a = Math.Acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
            double t = arg(c2.c - c1.c);
            return new Segment(c1.c + polar(c1.r, t + a), c1.c + polar(c1.r, t - a));
        }
        //他ヘロンの公式を使ったり。高さだす、交点の投影点求める、投影点から平行線へのベクトル出す、みたいなの)
        //16.11 点の内包
        //IN:2,ON:1,OUT:0
        static public int contains(Polygon g, Point p)
        {
            int n = g.Count;
            bool x = false;
            for(var i=0;i<n;++i)
            {
                Point a = g[i] - p, b = g[(i + 1) % n] - p;
                if (Math.Abs(cross(a, b)) < Consts.EPS && dot(a, b) < Consts.EPS) return 1;
                if(b.Y<a.Y)
                {
                    var t = a;
                    a = b;
                    b = t;
                }
                if (a.Y < Consts.EPS && Consts.EPS < b.Y && Consts.EPS < cross(a, b)) x = !x;
            }
            return (x ? 2 : 0);
        }
        //他、xの最大・最小値を使って半直線を作り、各辺との交差、点を通る場合、辺と平行かつ通る場合を考えていく方法もあり
        //半直線：判定対象点とPolygonの右端との差を使って適当に作る
        //Polygonの各辺ごとに処理する
        //  ccwでライン上にあるか判定
        //  両方の点を通る場合(平行&通る):辺と点を合わせて1点と考える。次の辺は飛ばす
        //  点を通る場合：Ｖ、Λの場合は無視する。j+1の点を通る場合は次の処理に任す

    }
    class Program
    {
        static public long[] Sarray() { return ReadLine().Trim().Split().Select(long.Parse).ToArray(); }
        static public List<long> Slist() { return ReadLine().Split().Select(long.Parse).ToList(); }


        static void Main(string[] args)
        {
            var g = Sarray()[0];
            var poly = new Polygon();
            for (var i = 0; i < g; ++i)
            {
                var p = Sarray();
                poly.Add(new Point(p[0], p[1]));
            }
            var min = poly.Min(e => e.X);
            var max = poly.Max(e => e.X);
            var q = Sarray()[0];
            var num = poly.Count;
            var start = 0;
            if (poly[0].Y == poly[num - 1].Y)
                ++start;
            for (var i = 0; i < q; ++i)
            {
                var p = Sarray();
                var pos = new Point(p[0], p[1]);
                WriteLine(VecCalc.contains(poly, pos));
            }
        }
    }
}