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;
class Program
{
	static void Main()
	{
    long n = long.Parse(Console.ReadLine());
    Vector2[] polygon = new Vector2[n];//多角形の頂点
    for(long i = 0; i < n; i++)
    {
      long[] nums = Array.ConvertAll(Console.ReadLine().Split(' '),long.Parse);//１行ごとに受け取る
      polygon[i] = new Vector2(nums[0], nums[1]);
    }

    long q = long.Parse(Console.ReadLine());
    for(long i = 0; i < q; i++)
    {
      long[] numsa = Array.ConvertAll(Console.ReadLine().Split(' '),long.Parse);
      Vector2 aimPoint = new Vector2(numsa[0], numsa[1]);
      Console.WriteLine(Vector2.PolygonPointContain(polygon, aimPoint));
    }
	}
}

class Vector2//2次元ベクトル
{
static decimal EPS = 1e-10m;//小数誤差比較

  public Vector2 (decimal X, decimal Y)
  {
    this.x = X;
    this.y = Y;
  }

  public decimal x {private set; get;}
  public decimal y {private set; get;}

  public static Vector2 operator + (Vector2 ob1, Vector2 ob2)//ベクトルの基本演算
  {
    return new Vector2 (ob1.x + ob2.x, ob1.y + ob2.y);
  }
  public static Vector2 operator - (Vector2 ob1, Vector2 ob2)
  {
    return new Vector2 (ob1.x - ob2.x, ob1.y - ob2.y);
  }
  public static Vector2 operator * (Vector2 ob, decimal scalar)
  {
    return new Vector2 (ob.x * scalar, ob.y * scalar);
  }
  public static Vector2 operator * (decimal scalar, Vector2 ob)
  {
    return new Vector2 (ob.x * scalar, ob.y * scalar);
  }
  public static Vector2 operator / (Vector2 ob, decimal scalar)
  {
    return new Vector2 (ob.x / scalar, ob.y / scalar);
  }

  public decimal Length()//ベクトルの長さの2乗
  {
    return x * x + y * y;
  }
  public static decimal Distance(Vector2 ob1, Vector2 ob2)//2点間の距離
  {
    return (decimal)Math.Sqrt((double)((ob1.x-ob2.x) * (ob1.x-ob2.x) + (ob1.y-ob2.y) * (ob1.y-ob2.y)));
  }
  public static decimal DotProduct(Vector2 ob1, Vector2 ob2)//内積
  {
    return ob1.x * ob2.x + ob1.y * ob2.y;
  }
  public static decimal CrossProduct(Vector2 ob1, Vector2 ob2)//外積。第2引数が反時計回り側で正。
  {
    return ob1.x * ob2.y - ob1.y * ob2.x;
  }
  public static decimal Arg(Vector2 p)//x軸に対する偏角
  {
    return (decimal)Math.Atan2((double)p.y, (double)p.x);
  }
  public static Vector2 PoralCoordinate(decimal radius, decimal angle)//長さと座標から極座標にする
  {
    return new Vector2(radius * (decimal)Math.Cos((double)angle), radius * (decimal)Math.Sin((double)angle));
  }

  public static Vector2 Projection(Vector2 beginPoint, Vector2 endPoint, Vector2 point)//点の射影
  {
    Vector2 segment = endPoint - beginPoint;
    decimal ratio = Vector2.DotProduct(point - beginPoint, segment) / segment.Length();
    return beginPoint + segment * ratio;//始点にたす
  }

public static long WhereVector(Vector2 beginPoint, Vector2 endPoint, Vector2 point)
  {//ベクトルに対する点の位置
    Vector2 segment = endPoint - beginPoint;
    Vector2 aimVec = point - beginPoint;
    if(Vector2.CrossProduct(segment, aimVec) > EPS)
      return 1;//反時計回り側
    else if(Vector2.CrossProduct(segment, aimVec) < -EPS)
      return 2;//時計回り側
    else if(Vector2.DotProduct(segment, aimVec) < -1+EPS)
      return 3;//ベクトル反対向きの側
    else if(segment.Length() < aimVec.Length())
      return 4;//ベクトル向きの側
    else
      return 5;//ベクトル上
  }

  public static long IsIntersect(Vector2 vecA, Vector2 vecB,
    Vector2 vecAsub, Vector2 vecBsub)//2線分の交差判定
  {
    bool answer = false;

    if(Vector2.WhereVector(vecA, vecB, vecAsub) + Vector2.WhereVector(vecA, vecB, vecBsub) == 3
    && Vector2.WhereVector(vecAsub, vecBsub, vecA) + Vector2.WhereVector(vecAsub, vecBsub, vecB) == 3)
      answer = true;
    if(Vector2.WhereVector(vecA, vecB, vecAsub) == 5 || Vector2.WhereVector(vecA, vecB, vecBsub) == 5
    || Vector2.WhereVector(vecAsub, vecBsub, vecA) == 5 || Vector2.WhereVector(vecAsub, vecBsub, vecB) == 5)
      answer = true;
    return((answer) ? 1 : 0);
  }

  public static Vector2 IntersectPoint(Vector2 vecA, Vector2 vecB, 
    Vector2 vecAsub, Vector2 vecBsub)//2線分の交点
  {
    Vector2 leftPoint = Vector2.Projection(vecA, vecB, vecAsub);//線分左端点の射影
    Vector2 rightPoint = Vector2.Projection(vecA, vecB, vecBsub);//線分右端点の射影
    decimal leftLength = (vecAsub - leftPoint).Length();
    decimal rightLength = (vecBsub - rightPoint).Length();

    leftLength = (decimal)(Math.Sqrt((double)leftLength));
    rightLength = (decimal)(Math.Sqrt((double)rightLength));
    
    if(leftLength < EPS) return leftPoint;
    else if(rightLength < EPS) return rightPoint;
    decimal ratio = leftLength / (leftLength + rightLength);
    return (leftPoint + ratio * (rightPoint - leftPoint));
  }

public static Vector2[] circleLineIntersection(Vector2 centerPoint, decimal circleRadius, 
    Vector2 beginPoint, Vector2 endPoint)//円と直線の交点
  {
    Vector2[] answers = new Vector2[2];
    Vector2 segment = endPoint - beginPoint;
    Vector2 unitSegment = segment / (decimal)Math.Sqrt((double)segment.Length());
    Vector2 circleProjection = Projection(beginPoint, endPoint, centerPoint);//交点の中点
    decimal lineLength = 
      (decimal)Math.Sqrt((double)(circleRadius*circleRadius - (circleProjection-centerPoint).Length()));//端点と中点の距離
    //Console.WriteLine(unitSegment.x+" "+unitSegment.y);
    answers[0] = circleProjection + (unitSegment * lineLength);
    answers[1] = circleProjection - (unitSegment * lineLength);
    return answers;
  }

  public static Vector2[] CircleIntersection(Vector2 centerPointA, decimal circleRadiusA, 
      Vector2 centerPointB, decimal circleRadiusB)//2円の交点
    {
      Vector2[] answers = new Vector2[2];
      decimal centerDistance = Distance(centerPointA, centerPointB);//2円の中心間距離
      decimal centerAngle = Arg(centerPointB - centerPointA);
      decimal intersectionAngle = (decimal)Math.Acos((double)(circleRadiusA*circleRadiusA
        + centerDistance*centerDistance - circleRadiusB*circleRadiusB)
        /(double)(2*circleRadiusA*centerDistance));//余弦定理
      answers[0] = centerPointA + PoralCoordinate(circleRadiusA, centerAngle+intersectionAngle);
      answers[1] = centerPointA + PoralCoordinate(circleRadiusA, centerAngle-intersectionAngle); 
      if(answers[0].x > answers[1].x || (Math.Abs(answers[0].x - answers[1].x) < EPS && answers[0].y > answers[1].y))
      {
        Vector2 swapMemo = answers[0];
        answers[0] = answers[1];
        answers[1] = swapMemo;
      }
      return answers; 
    }

    public static decimal TriangleAria(Vector2 PointA, Vector2 PointB, Vector2 PointC)//3頂点に対する三角形の面積
    {
      decimal a = PointB.x - PointA.x;
      decimal b = PointB.y - PointA.y;
      decimal c = PointC.x - PointA.x;
      decimal d = PointC.y - PointA.y;
      return (Math.Abs(a*d-b*c)) / 2;
    }

    public static long PolygonPointContain(Vector2[] polygon, Vector2 aimPoint)
      //多角形が点を含めば2,辺上は1,他は0
    {
      long n = polygon.Length;
      bool answer = false;
      for(int i = 0; i < n; i++)
      {
        if(WhereVector(polygon[i], polygon[(i+1)%n], aimPoint) == 5) return 1;//点は多角形上
        
        Vector2 toEgdeA = polygon[i] - aimPoint;//点から、多角形の各頂点へ線分を引く
        Vector2 toEgdeB = polygon[(i+1)%n] - aimPoint;
        if(toEgdeA.y > toEgdeB.y)
        {
          Vector2 swapMemo = toEgdeA;
          toEgdeA = toEgdeB;
          toEgdeB = swapMemo;
        }
        if(toEgdeA.y < EPS && toEgdeB.y > EPS && CrossProduct(toEgdeA, toEgdeB) > EPS)
        {//点をx軸正の方向に伸ばして、奇数回交われば内部。
          answer = !answer;
        }
      }
      return ((answer) ? 2 : 0);
    }
}