Problem:
Castle in the Sky
Tsuruga, the Castle in the Sky, floats in the sky above the country of Aizu. There are days when sunlight is blocked by the castle. Compensation is paid to the inhabitants of the areas where sunlight is blocked for a certain number of days. As the compensation payer for the country of Aizu, you will need to verify that there was no sunlight at the location on that day from the daily location of the astle and the list of locations where compensation has been applied for.
Given the location of the castle in the sky, and a location on the ground in the country of AIzu, write a program to determine if the location was in shadow on that day. You do not need to think about the movement of the castle or the sun, because you will determine at a specific time whether it was in the shadow or not. The location of the sun is a point of no size at $x=y=0,z=10^6$, the castle in the sky is a convex polygon in the plane at $z=100$, and the location on the ground is a point of no size at $z=0$. If the line connecting a point and the sun is blocked by the castle in the sky, the point will be in shadow.
Input
The input is given in the following form.
$N$
$xt_1$ $yt_1$
$xt_2$ $yt_2$
:
$xt_N$ $yt_N$
$Q$
$xa_1$ $ya_1$
$xa_2$ $ya_2$
:
$xa_Q$ $ya_Q$
In the first line, the number of points $N$ ($3 \leq N \leq 3 \times 10^4$) that represent the region of the castle in the sky, is given. In the following $N$ lines, the integer coordinates $xt_i$,$yt_i$ ($-10^8 \leq xt_i,yt_i \leq 10^8$) of the vertices that make up the region are given in counterclockwise around the center of gravity of the region. However, no vertices with the same coordinates are given ($xt_i \ne xt_j$ or $yt_i \ne yt_j$ for $i \ne j$). Also, the area of the region can be considered to be greater than zero. In the subsequent line, the number $Q$ ($1 \leq Q \leq 6 \times 10^4$) of locations where compensation has been applied is given. In the following $Q$ lines, the coordinates $xa_i,ya_i$ ($-10^8 \leq xa_i,ya_i \leq 10^8$) of the locations where compensation was applied are given in integers. Note that the coordinates of the location where the application for compensation was made can be considered to be at least $10^{-3}$ away from the shadow outline of the castle.
Output
For each location where compensation was applied for, output "1" if it is in the shadow, and "0" if it is not, in a line.
Sample Input and Output
Sample Input 1
6
0 0
4 0
6 3
5 5
1 5
0 3
5
2 2
6 6
3 1
5 1
-1 -1
Sample Output 1
1
0
1
0
0
Sample Input ２
4
100000 100000
101000 100000
101000 101000
100000 101000
2
100005 100005
101005 101005
Sample Output 2
0
1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#ifndef ONLINE_JUDGE
#define _GLIBCXX_DEBUG
#include <iostream>
template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {return os<<'(' <<p.first<<", "<<p.second<<')';}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {os<<'[';for(auto it=v.begin();it!=v.end();++it){os<<*it; if(next(it)!=v.end()){os<<", ";}}return os<<']';}
template <typename T>
ostream& operator<<(ostream& os, const vector<vector<T>>& vv) {os<<"[\n";for(auto it=vv.begin();it!=vv.end();++it){os<<"  "<<*it;if(next(it)!=vv.end()){os<<",\n";}else{os<<"\n";}}return os<<"]";}
#define dump(x) cerr << #x << " = " << (x) << '\n'
#else
#define dump(x) (void)0
#endif
using ll = long long;
using ld = long double;
using P = pair<ll,ll>;
template<class T> using pq = priority_queue<T>;
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>;
#define out(x) cout<<x<<'\n'
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define OVERLOAD_REP(_1,_2,_3,name,...) name
#define REP1(i,n) for (auto i = std::decay_t<decltype(n)>{}; (i) < (n); ++(i))
#define REP2(i, l, r) for (auto i = (l); (i) < (r); ++(i))
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP2, REP1)(__VA_ARGS__)
template<class T> inline bool chmin(T& a, T b) {if(a > b){a = b; return true;} else {return false;}};
template<class T> inline bool chmax(T& a, T b) {if(a < b){a = b; return true;} else {return false;}};
const ll INF=(1LL<<60);
const ll mod=998244353;
using Graph = vector<vector<ll>>;
using Network = vector<vector<pair<ll,ll>>>;
using Grid = vector<string>;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
const int dx2[8] = {1, 1,  1, 0,  0, -1, -1, -1};
const int dy2[8] = {1, 0, -1, 1, -1,  1,  0, -1};

// #include "../geo.hpp"

// #pragma once

using D = long double;
const D EPS = 1e-12L;
const D PI = acosl(-1.0L);
using P2 = complex<D>;
struct L2{P2 a, b;};
struct S2{P2 a, b;};
using G2 = vector<P2>;

int sgn(D x){return (x>EPS)-(x<-EPS);}
int cmp(D a, D b){return sgn(a-b);}
bool eq(D a, D b){return cmp(a, b)==0;}
bool lt(D a, D b){return cmp(a, b)<0;}
bool le(D a, D b){return cmp(a, b)<=0;}
bool gt(D a, D b){return cmp(a, b)>0;}
bool ge(D a, D b){return cmp(a, b)>=0;}
bool eqP2(P2 a, P2 b){return eq(real(a), real(b)) && eq(imag(a), imag(b));}
bool ltP2(P2 a, P2 b) {
    return lt(real(a), real(b)) || (eq(real(a), real(b)) && lt(imag(a), imag(b)));
}

D dot(P2 a, P2 b) {return real(conj(a)*b);}
D cross(P2 a, P2 b) {return imag(conj(a)*b);}
int ccw(P2 a, P2 b, P2 c) {
    b-=a; c-=a;
    auto cr=cross(b, c), dt=dot(b, c);
    if (cr > EPS) return +1;       // counter clockwise
    if (cr < -EPS) return -1;      // clockwise
    if (dt < -EPS) return +2;         // c--a--b
    if (lt(norm(b), norm(c))) return -2; // a--b--c
    return 0;                  // a--c--b
}
int turn(P2 a, P2 b, P2 c) { return sgn(cross(b - a, c - a)); }

P2 rot(P2 a, D th) { return a*polar<D>(1, th); }
P2 rot90(P2 a) { return P2(-imag(a), real(a)); }
bool ltP2Arg(P2 a, P2 b) {
    auto up = [](P2 p) { return (imag(p) > 0 || (eq(imag(p), 0) && ge(real(p), 0))); };
    if (up(a) != up(b)) return up(a);
    if (!eq(cross(a, b), 0)) return cross(a, b) > 0;
    return lt(norm(a), norm(b));
}

inline void rd(P2& p) {D x, y; cin>>x>>y; p = P2(x, y);}
#define setp(n) cout<<setprecision(n)<<fixed
inline void pr(const P2& p) {setp(12); cout<<real(p)<<' '<<imag(p)<<'\n';}

// ----------------------------------------------------------------------------------

P2 proj(L2 l, P2 p) { P2 a=p-l.a, b=l.b-l.a; return l.a+b*dot(a, b)/norm(b);}
P2 refl(L2 l, P2 p) { return proj(l, p)*2.0L - p; }
bool isParallel(L2 l, L2 m){ return eq(cross(l.a-l.b, m.a-m.b), 0); }
bool isPerp(L2 l, L2 m){ return eq(dot(l.a-l.b, m.a-m.b), 0); }

bool isLL(L2 l, L2 m){ return !eq(cross(l.a-l.b, m.a-m.b), 0); }
bool isLS(L2 l, S2 s){ return turn(l.a, l.b, s.a)*turn(l.a, l.b, s.b)<=0; }
bool isSS(S2 s, S2 t) {
    return
    ccw(s.a,s.b,t.a)*ccw(s.a,s.b,t.b) <= 0 &&
    ccw(t.a,t.b,s.a)*ccw(t.a,t.b,s.b) <= 0;
}

P2 cpLL(L2 l, L2 m) {
    P2 a=l.b-l.a, b=m.b-m.a;
    D d=cross(a, b);
    if (eq(d, 0)) return P2(INF, INF); // parallel
    return l.a + a*cross(m.b-l.a,b)/d;
}

D distLP(L2 l, P2 p) { return abs(cross(l.b-l.a, p-l.a))/abs(l.b-l.a); }
D distSP(S2 s, P2 p) {
    P2 a=s.a, b=s.b;
    if (le(dot(b-a, p-a), 0)) return abs(p-a);
    if (le(dot(a-b, p-b), 0)) return abs(p-b);
    return distLP({a,b}, p);
}
D distSS(S2 s, S2 t) {
    if (isSS(s, t)) return 0;
    return min({distSP(s, t.a), distSP(s, t.b), distSP(t, s.a), distSP(t, s.b)});
}

D area(G2 g) {
    D s=0;
    int n=g.size();
    rep(i, n) s+=cross(g[i], g[(i+1)%n]);
    return s/2.0L;
}

bool isConvex(G2 g) {
    int n=g.size();
    if (n < 3) return false;
    int dir = 0;
    rep(i,n){
        int s = turn(g[i], g[(i+1)%n], g[(i+2)%n]);
        if (s == 0) return false; // -> continue : allows three points on a line
        if (dir == 0) dir = s;
        else if (dir*s < 0) return false;
    }
    return true;
}

int inG(G2 g, P2 p) {
    bool in=false;
    int n=g.size();
    rep(i, n) {
        P2 a=g[i], b=g[(i+1)%n];
        if (ccw(a, b, p) == 0) return 1; // on boundary
        if (a.imag() > b.imag()) swap(a, b);
        if (le(a.imag(), p.imag()) && lt(p.imag(), b.imag()) && turn(a, b, p) > 0) in=!in;
    }
    return in ? 2 : 0; // inside : outside
}

G2 hull(G2 g) {
    sort(all(g), ltP2);
    g.erase(unique(all(g), eqP2), g.end());
    if (g.size()<=1) return g;
    G2 lo, up;
    for (auto &p:g) {
        while (lo.size()>=2 && turn(lo[lo.size()-2], lo.back(), p)<=0) lo.pop_back(); //-> turn()<0 : allow three points on a line
        lo.push_back(p);
    }
    reverse(all(g));
    for (auto &p:g) {
        while (up.size()>=2 && turn(up[up.size()-2], up.back(), p)<=0) up.pop_back(); // -> turn()<0 : allow three points on a line
        up.push_back(p);
    }
    lo.pop_back(); up.pop_back();
    lo.insert(lo.end(), all(up));
    return lo;
}

pair<P2, P2> diameter(G2 g) {
    auto h = hull(g);
    int n=h.size();
    if(n==0) return {P2(0,0), P2(0,0)};
    if(n==1) return {h[0], h[0]};
    auto area2=[&](int i, int j, int k) {return abs(cross(h[j]-h[i], h[k]-h[i]));};
    D maxd=0;
    pair<P2, P2> res={h[0], h[0]};
    int j=1;
    rep(i, n) {
        int ni=(i+1)%n;
        while (gt(area2(i, ni, (j+1)%n), area2(i, ni, j))) j=(j+1)%n;
        if (gt(abs(h[i]-h[j]), maxd)) maxd=abs(h[i]-h[j]), res={h[i], h[j]};
        if (gt(abs(h[ni]-h[j]), maxd)) maxd=abs(h[ni]-h[j]), res={h[ni], h[j]};
    }
    return res;
}

int inConvex(const G2& h, P2 p){
  int n = (int)h.size();
  if (n==0) return 0;
  if (n==1) return eqP2(h[0], p) ? 2 : 0;
  if (n==2) return (sgn(cross(h[1]-h[0], p-h[0]))==0 && sgn(dot(p-h[0], p-h[1]))<=0) ? 2 : 0;
  if (turn(h[0], h[1], p) < 0) return 0;
  if (turn(h[0], h[n-1], p) > 0) return 0;

  int L = 1, R = n-1;
  while (R - L > 1){
    int M = (L + R) / 2;
    (turn(h[0], h[M], p) >= 0) ? L = M : R = M;
  }
  int s = turn(h[L], h[(L+1)%n], p);
  return s==0 ? 2 : (s>0 ? 1 : 0);
}

G2 cutConvex(G2 h, L2 l) {
    int n=h.size();
    G2 res;
    if (n==0) return res;
    auto inside=[&](P2 p){ return turn(l.a, l.b, p) >= 0; };
    rep(i, n) {
        P2 a=h[i], b=h[(i+1)%n];
        bool ina=inside(a), inb=inside(b);
        if (ina&&inb) res.push_back(b);
        else if (ina&&!inb) {
            res.push_back(cpLL({a,b}, l));
        }
        else if (!ina&&inb) {
            res.push_back(cpLL({a,b}, l));
            res.push_back(b);
        }
    }
    return res;
}

pair<P2, P2> closestPair(G2 g) {
    auto ps = g;
    int n=ps.size();
    if (n < 2) return {P2(0,0), P2(0,0)};
    sort(all(ps), ltP2);
    rep(i, n-1) if (eqP2(ps[i], ps[i+1])) return {ps[i], ps[i]};

    D mind = norm(ps[0]-ps[1]);
    pair<P2, P2> res = {ps[0], ps[1]};
    set<pair<D,int>> box;
    int j=0;
    rep(i, n) {
        D xi=real(ps[i]), yi=imag(ps[i]);
        D rad = sqrtl(mind);
        while (j<i && gt(xi - real(ps[j]), rad)) {
            box.erase({imag(ps[j]), j});
            j++;
        }
        auto it = box.lower_bound({yi - rad, -1});
        for (; it != box.end() && le(it->first, yi + rad); ++it) {
            int k = it->second;
            D d = norm(ps[i]-ps[k]);
            if (lt(d, mind)) { mind=d, res={ps[i], ps[k]}, rad = sqrtl(mind); }
        }
        box.insert({yi, i});
    }
    return res;
}


struct C2 { P2 o; D r; };

C2 makeC2(P2 a, P2 b) {
    return C2{(a+b)/D(2), abs(a-b)/D(2)};
}
C2 makeC2(P2 a, P2 b, P2 c) {
    P2 B=b-a, C=c-a;
    D d=2*cross(B, C);
    if (eq(d, 0)) {
        D ab=norm(B), bc=norm(b-c), ca=norm(c-a);
        if (le(ab, bc) && le(ab, ca)) return makeC2(a, b);
        if (le(bc, ca)) return makeC2(b, c);
        return makeC2(c, a);
    }
    P2 o=a+(rot90(B)*norm(C)-rot90(C)*norm(B))/d;
    return C2{o, abs(o-a)};
}

C2 incircle(P2 a, P2 b, P2 c) {
    D ab=abs(b-a), bc=abs(c-b), ca=abs(a-c);
    P2 o=(a*bc+b*ca+c*ab)/(ab+bc+ca);
    D r=abs(cross(b-a, o-a))/abs(b-a);
    return C2{o, r};
}

vector<P2> cpCL(L2 l, C2 c) {
    // todo
    // vector<P2> res;
    // P2 a=l.a-c.o, d=l.b-l.a;
    // D A=norm(d), B=2*dot(a, d), C=norm(a)-c.r*c.r;
    // if (le(A, 0)) {
    //     if (eq(abs(a), c.r)) res.push_back(l.a);
    //     return res;
    // }
    // D Dlt=B*B-4*A*C;
    // if (lt(Dlt, 0)) return res;
    // D s = le(Dlt, 0) ? 0 : sqrtl(max<D>(0, Dlt));
    // D t1 = (-B - s)/(2*A), t2 = (-B + s)/(2*A);
    // res.push_back(c.o + a + d*t1);
    // if (gt(Dlt, 0)) res.push_back(c.o + a + d*t2);
    // return res;
}

vector<P2> cpCC(C2 c1, C2 c2) {
    vector<P2> res;
    P2 d=c2.o-c1.o;
    D L=abs(d);
    if (eq(L, 0)) return res;
    D a=(c1.r*c1.r-c2.r*c2.r+L*L)/(2*L), h2=c1.r*c1.r-a*a;
    if (lt(h2, 0)) return res;
    P2 m=c1.o+d*(a/L), n=rot90(d)*( (lt(h2, 0) ? 0 : sqrtl(max<D>(0, h2))/L) );
    res.push_back(m-n);
    if (gt(h2, 0)) res.push_back(m+n);
    return res;
}

D isaCC(C2 c1, C2 c2) {
    D d=abs(c1.o-c2.o), r1=c1.r, r2=c2.r;
    if (ge(d, r1+r2)) return 0;
    if (le(d, abs(r1-r2))) {
        D r=min(r1, r2);
        return PI*r*r;
    }
    auto f = [&] (D z) { return max<D>(-1, min<D>(1, z)); };
    D a = 2*acosl(f((d*d+r1*r1-r2*r2)/(2*d*r1)));
    D b = 2*acosl(f((d*d+r2*r2-r1*r1)/(2*d*r2)));
    return 0.5L*(r1*r1*(a-sinl(a)) + r2*r2*(b-sinl(b)));
}

vector<L2> tangCP(C2 c, P2 p) {
    vector<L2> res;
    P2 v = p - c.o;
    D d2 = norm(v), r2 = c.r*c.r;
    if (lt(d2, r2)) return res;
    if (eq(d2, r2)) {
        res.push_back({c.o+v*(r2/d2), p});
        return res;
    }
    D h = c.r*sqrtl(max<D>(0, d2 - r2));
    P2 n1 = (v*r2 - rot90(v)*h)/d2;
    P2 n2 = (v*r2 + rot90(v)*h)/d2;
    res.push_back({c.o+n1, p});
    res.push_back({c.o+n2, p});
    return res;
}

vector<L2> tangCC(C2 c1, C2 c2) {
    vector<L2> res;
    P2 d = c2.o-c1.o;
    D L=abs(d);
    if (eq(L, 0)) return res;
    P2 e = d/L;
    auto add = [&] (int s) {
        D c=(s*c2.r - c1.r)/L;
        if (gt(c*c, 1)) return;
        D s2 = max<D>(0, 1 - c*c);
        if (eq(s2, 0)) {
            P2 n = e*c;
            res.push_back({c1.o-n*c1.r, c2.o-n*c2.r});
        } else {
            D s = sqrtl(s2);
            P2 n1 = e*c + rot90(e)*s;
            P2 n2 = e*c - rot90(e)*s;
            res.push_back({c1.o-n1*c1.r, c2.o-n1*c2.r});
            res.push_back({c1.o-n2*c1.r, c2.o-n2*c2.r});
        }
    };
    add(+1); // external
    add(-1); // internal
    return res;
}

C2 mec(G2 ps) {
    auto inC2=[&](C2 c, P2 p){ return le(abs(c.o - p), c.r); };
    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());
    shuffle(all(ps), rng);
    int n=ps.size();
    if(n==0) return C2{P2(0,0), 0};
    C2 c{ps[0], 0};
    rep(i, n) {
        if (inC2(c, ps[i])) continue;
        c={ps[i], 0};
        rep(j, i) {
            if (inC2(c, ps[j])) continue;
            c=makeC2(ps[i], ps[j]);
            rep(k, j) {
                if (inC2(c, ps[k])) continue;
                c=makeC2(ps[i], ps[j], ps[k]);
            }
        }
    }
    return c;
}

vector<P2> cpSegs(vector<S2> ss) {
    struct E { D x; int t; D y, y1, y2; }; // t: 0=add(H), 1=query(V), 2=remove(H)
    vector<E> es; es.reserve(ss.size()*2);

    for(auto s: ss) {
        if (eq(s.a.imag(), s.b.imag())) {
            if (gt(s.a.real(), s.b.real())) swap(s.a, s.b);
            es.push_back({s.a.real(), 0, s.a.imag(), 0, 0});
            es.push_back({s.b.real(), 2, s.a.imag(), 0, 0});
        } else {
            if (gt(s.a.imag(), s.b.imag())) swap(s.a, s.b);
            es.push_back({s.a.real(), 1, 0, s.a.imag(), s.b.imag()});
        }
    }

    sort(all(es), [](E a, E b) {
        if (!eq(a.x, b.x)) return lt(a.x, b.x);
        return a.t < b.t;
    });

    multiset<D> active;
    vector<P2> res; res.reserve(ss.size());
    for (auto e : es) {
        if (e.t == 0) { // add
            active.insert(e.y);
        } else if (e.t == 2) { // remove
            auto it = active.find(e.y);
            if (it != active.end()) active.erase(it);
        } else { // query
            for (auto it = active.lower_bound(e.y1); it != active.end() && le(*it, e.y2); ++it) {
                res.push_back(P2(e.x, *it));
            }
        }
    }

    sort(all(res), ltP2);
    res.erase(unique(all(res), eqP2), res.end());
    return res;
}

// === begin: Half-Plane Intersection (angle-free) ===

struct HP{
  L2 l;
  HP(){} HP(L2 _l):l(_l){}
  bool inside(P2 p) const { return turn(l.a,l.b,p) >= 0; }
};
P2 dir(const HP& h){ return h.l.b - h.l.a; }
bool ltHPArg(const HP& a, const HP& b){
  return ltP2Arg(dir(a),dir(b));
}
// 同角は最左の半平面 1 本に正規化
vector<HP> normalizeHP(vector<HP> v){
  sort(all(v), ltHPArg);
  vector<HP> u; u.reserve(v.size());
  for (auto &h: v){
    if (!u.empty() && eq(cross(dir(u.back()), dir(h)), 0)){
      if (h.inside(u.back().l.a)) continue; 
      u.back() = h;
    }else u.push_back(h);
  }
  return u;
}

// 本体：半平面の共通部分（左側）を凸多角形で返す（空集合は空配列）
G2 hpi(vector<HP> H){
  H = normalizeHP(move(H));
  deque<HP> dq;
  deque<P2> I;

  auto push_hp = [&](HP h){
    while(!I.empty() && !h.inside(I.back())){ dq.pop_back(); I.pop_back(); }
    while(!I.empty() && !h.inside(I.front())){ dq.pop_front(); I.pop_front(); }
    if(!dq.empty() && eq(cross(dir(dq.back()), dir(h)), 0)){
      if(h.inside(dq.back().l.a)) dq.back() = h;
      return;
    }
    if(!dq.empty()) I.push_back(cpLL(dq.back().l, h.l));
    dq.push_back(h);
  };

  for(auto &h: H) push_hp(h);

  while(!I.empty() && !dq.front().inside(I.back())){ dq.pop_back(); I.pop_back(); } // Be cafeful for front, back.
  while(!I.empty() && !dq.back().inside(I.front())){ dq.pop_front(); I.pop_front(); }

  if(dq.size()<3) return {};

  G2 poly; poly.reserve(dq.size());
  int n = dq.size();
  rep(i,n) poly.push_back(cpLL(dq[i].l, dq[(i+1)%n].l));
  return poly;
}

// === end: Half-Plane Intersection ===




void solve() {
    ll n;cin>>n;
    G2 g(n);
    rep(i, n) {
        ld x, y;cin>>x>>y;
        x *= 10000.0L/9999.0L;
        y *= 10000.0L/9999.0L;
        P2 p(x, y);
        g[i] = p;
    }
    ll q;cin>>q;
    while(q--) {
        P2 p;rd(p);
        cout << ((inConvex(g, p) >= 1)? 1 : 0 )<< "\n";
    }
}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int t = 1;
    while (t--) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 4160
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld=long double;
#define fi first
#define se second
#define i128 __int128_t
#define all(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define si(a) (long)(a.size())
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}
const int INF=1e9+100;
const long INFL=3e18+100;
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

using Real=ld;
using Point=complex<Real>;
Real EPS=1e-12;
Real cross(const Point &a, const Point &b){
    return (a.real()*b.imag()-a.imag()*b.real());
}
Real dot(const Point &a, const Point &b){
    return (a.real()*b.real()+a.imag()*b.imag());
}
int isContained(const vector<Point>&g, const Point &p){
    bool in=false;
    int n=si(g);
    rep(i,n){
        Point a=g[i]-p;
        Point b=g[(i+1)%n]-p;
        if(imag(a)>imag(b)) swap(a,b);
        if(imag(a)<=EPS&&EPS<imag(b)&&cross(a,b)<-EPS) in=!in;
        if(cross(a,b)==0&&dot(a,b)<=0) return 1;
    }
    return (in?2:0);
}
int ccw(const Point &a, const Point &b, const Point &c) {
    Point d = b - a;
    Point e = c - a;
    if (cross(d, e) > EPS) return 1;
    if (cross(d, e) < -EPS) return -1;
    if (dot(d, e) < 0) return 2;
    if (norm(d) < norm(e)) return -2;
    return 0;
}

int main(){
    ld H=1e6;
    
    int N;
    cin>>N;
    
    vector<Point> P(N);
    rep(i,N){
        ld x,y;
        cin>>x>>y;
        
        x=x/(H-100)*H;
        y=y/(H-100)*H;
        P[i]={x,y};
    }
    int Q;
    cin>>Q;
    rep(_,Q){
        ld x,y;
        cin>>x>>y;

        int ok=1;
        int ng=N-1;
        while(ng-ok>1){
            int m=(ok+ng)/2;
            if(ccw(P[0], {x,y}, P[m])==-1) ok=m;
            else ng=m;
        }
        vector<Point> g={P[0],P[ok],P[ok+1]};
        if(isContained(g, Point(x,y))){
            cout<<1<<"\n";
        }
        else{
            cout<<0<<"\n";
        }
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4352
final_rank: 1

code_snippet: #include<bits/stdc++.h>

using namespace std;

#define rep(i, l, n) for(int i = int(l); i < int(n); i++)
#define ll long long
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()

template<class T> bool chmin(T &a, T b) {if(a > b) {a = b; return true;} return false;}
template<class T> bool chmax(T &a, T b) {if(a < b) {a = b; return true;} return false;}
template<class T> using spq = priority_queue<T, vector<T>, greater<T>>;

// bool -> Yes/No
string answer(bool b) {return b ? "Yes" : "No";}

void fix(int k) {cout << fixed << setprecision(k);}

const int inf = 2e9;
const long long INF = 2e18;
const long double eps = 1e-12;
int dx[] = {0, -1, 0, 1, -1, -1, 1, 1}, dy[] = {1, 0, -1, 0, 1, -1, -1, 1};

using ld = long double;

bool inside(vector<ld> &vec, ld y) {
    if(vec.empty()) return false;
    assert(int(vec.size()) == 2);
    ld a = vec[0], b = vec[1];
    return (min(a, b) <= y && y <= max(a, b));
}

void main_program() {
    int n; cin >> n;
    ld x[n], y[n];
    rep(i, 0, n) cin >> x[i] >> y[i];
    int q; cin >> q;
    int qx[q], qy[q];
    rep(i, 0, q) cin >> qx[i] >> qy[i];
    ld k = 10000.00 / 9999.00;
    rep(i, 0, n) {
        x[i] *= k;
        y[i] *= k;
    }
    map<int, int> mp;
    rep(i, 0, q) mp[qx[i]] = -1;
    int m = mp.size();
    ld p[m]; vector<ld> lst[m];
    int idx = 0;
    for(auto[key, val] : mp) {
        p[idx] = key;
        mp[key] = idx++;
    }/*
    fix(10);
    rep(i, 0, n) {
        cout << x[i] << " " << y[i] << "\n";
    }*/
    rep(i, 0, n) {
        ld ax = x[i], ay = y[i];
        ld bx = x[(i + 1) % n], by = y[(i + 1) % n];
        if(ax > bx) swap(ax, bx), swap(ay, by);
        int d = lower_bound(p, p + m, ax) - p;
        //cout << i << " : ";
        //cout << ax << "," << ay << " , " << bx << "," << by << "\n";
        while(d < m && p[d] < bx) {
            ld xx = ax - p[d], yy = p[d] - bx;
            ld res = xx * by + yy * ay;
            lst[d++].emplace_back(res / (xx + yy));
        }
    }/*
    fix(10);
    rep(i, 0, m) {
        for(ld s : lst[i]) {
            cout << s << " ";
        }
        cout << "\n";
    }*/
    rep(i, 0, q) {
        idx = mp[qx[i]];
        cout << inside(lst[idx], qy[i]) << "\n";
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T = 1;
    //cin >> T;
    while(T--) {
        main_program();
    }
}
accuracy: 1
time_ms: 30
memory_kb: 12564
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define oke cout << "Yes" << '\n';
#define dame cout << "No" << '\n';
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
using HaiI = vector<vector<int>>;
using Hai2 = vector<vector<ll>>;
using HaiB = vector<vector<bool>>;
using Hai3 = vector<vector<vector<ll>>>;

using Point=complex<double>;
double PI=3.141526;
double EPS=1e-10;

inline bool equal(const double &a, const double &b) {
    return fabs(a - b) < 1e-10;
}

// 単位ベクトル(unit vector)を求める
Point unitVector(const Point &a) { return a / abs(a); }

// 法線ベクトル(normal vector)を求める
// 90度回転した単位ベクトルをかける
// -90度がよければPoint(0, -1)をかける
Point normalVector(const Point &a) { return a * Point(0, 1); }

// 内積(dot product) : a・b = |a||b|cosΘ
double dot(const Point &a, const Point &b) {
    return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積(cross product) : a×b = |a||b|sinΘ
double cross(const Point &a, const Point &b) {
    return (a.real() * b.imag() - a.imag() * b.real());
}

// 点pを反時計回りにtheta度回転
Point rotate(const Point &p, const double &theta) {
    return Point(cos(theta) * p.real() - sin(theta) * p.imag(),
                 sin(theta) * p.real() + cos(theta) * p.imag());
}

// ラジアン->度
double radianToDegree(const double &radian) { return radian * 180.0 / PI; }

// 度->ラジアン
double degreeToRadian(const double &degree) { return degree * PI / 180.0; }

// g は凸多角形 (CCW), p は判定点
// 含まれる:2, 辺上にある:1, 含まれない:0
int isContained(const vector<Point>& g, const Point& p) {
    int n = (int)g.size();
    const Point &g0 = g[0];

    // g0 より左にあるかチェック
    if (cross(g[1] - g0, p - g0) < -EPS) return 0;
    if (cross(g[n-1] - g0, p - g0) > EPS) return 0;

    // 辺上チェック (g0-g1, g0-gn-1 上)
    if (fabs(cross(g[1] - g0, p - g0)) <= EPS &&
		dot(g[1] - g0, p - g0) >= -EPS &&
		dot(g[0] - g[1], p - g[1]) >= -EPS) return 1;
    if (fabs(cross(g[n-1] - g0, p - g0)) <= EPS &&
        dot(g[n-1] - g0, p - g0) >= -EPS &&
        dot(g[0] - g[n-1], p - g[n-1]) >= -EPS) return 1;

    // 扇の中 → 二分探索
    int l = 1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        if (cross(g[m] - g0, p - g0) >= 0) l = m;
        else r = m;
    }

    // 三角形 (g0, g[l], g[l+1]) 内か判定
    double c = cross(g[l+1] - g[l], p - g[l]);
    if (fabs(c) <= EPS) return 1;      // 辺上
    return (c > 0 ? 2 : 0);
}


int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(15);
	int N;
	cin>>N;
	vector<Point> G(N);
	double Z=1e6;
	rep(i,N){
		double a,b;
		cin>>a>>b;
		a=a*Z/(Z-100);
		b=b*Z/(Z-100);
		G[i]=Point(a,b);
	}
	int Q;
	cin>>Q;
	rep(i,Q){
		double x,y;
		cin>>x>>y;
		Point R(x,y);
		int t = isContained(G,R);
		if(t==2){
			t=1;
		}else if(t==1){
			t=0;
		}

		cout<<t<<"\n";
	}
}
accuracy: 1
time_ms: 40
memory_kb: 3588
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#include <iomanip>
#include <numbers>
#include <cassert>
#include <numeric>
#ifdef _MSC_VER
#include <intrin.h>
#endif
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pint = pair<int, int>;
template<typename T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
template<typename T>
bool chmax(T & a, const T & b) { if (a < b) { a = b; return true; } return false; }
template<typename T>
bool chmin(T & a, const T & b) { if (a > b) { a = b; return true; } return false; }
const int inf = 1e9;
const ll linf = 1e18;
const int dy[] = { 0,0,1,-1 }, dx[] = { 1,-1,0,0 };
struct vecd {
    double x, y;
    double len() { return sqrt(x * x + y * y); }
    vecd operator+(const vecd& other) const {
        return { x + other.x,y + other.y };
    }
    vecd operator-(const vecd& other) const {
        return { x - other.x,y - other.y };
    }
    vecd operator*(const double& n) const {
        return { x * n,y * n };
    }
    vecd& operator+=(const vecd& other) {
        x += other.x, y += other.y;
        return *this;
    }
    vecd& operator-=(const vecd& other) {
        x -= other.x, y -= other.y;
        return *this;
    }
    bool operator<(const vecd& other) const {
        if (x == other.x)return y < other.y;
        else return x < other.x;
    }
};
double cross(vecd a, vecd b, vecd c) {
    vecd d1 = a - b;
    vecd d2 = c - b;
    return d1.x * d2.y - d2.x * d1.y;
}
int main() {
    int n; cin >> n;
    vector<vecd> ps(n);
    rep(i, n)cin >> ps[i].x >> ps[i].y;
    int q; cin >> q;
    rep(i, q) {
        vecd p;
        cin >> p.x >> p.y;
        p.x *= 1.0 - 100.0 / 1000000;
        p.y *= 1.0 - 100.0 / 1000000;
        int left = 2, right = n;
        while (left + 1 < right) {
            int mid = (left + right) / 2;
            if (cross(ps[0], ps[mid - 1], p) > 0) right = mid;
            else left = mid;
        }
        double c1 = cross(p, ps[left - 1], ps[0]);
        double c2 = cross(p, ps[0], ps[left]);
        double c3 = cross(p, ps[left], ps[left - 1]);
        if (c1 < 0 || c2 < 0 || c3 < 0)cout << 0 << endl;
        else cout << 1 << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3968
final_rank: 7

code_snippet: // Nyaan 大先生いつもお世話になっております。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

using ld = long double;
constexpr ld EPS = 1e-10;
const ld PI = acos(-1);

bool equals(ld a, ld b) { return abs(b - a) < EPS; }
int sign(ld a) { return equals(a, 0) ? 0 : (a > 0 ? 1 : -1); }

template <class R>
struct Point {
    R x, y;
    Point() : x(0), y(0) {}
    template <class T, class U>
    Point(T x0, U y0) : x(x0), y(y0) {}
    template <class T, class U>
    Point(const pair<T, U>& p) : x(p.first), y(p.second) {}

    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point& p) const { return Point(*this) += p; }
    Point operator-(const Point& p) const { return Point(*this) -= p; }
    Point operator*(const R& k) const { return Point(*this) *= k; }
    Point operator/(const R& k) const { return Point(*this) /= k; }
    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point& operator*=(const R& k) {
        x *= k, y *= k;
        return *this;
    }
    Point& operator/=(const R& k) {
        x /= k, y /= k;
        return *this;
    }
    bool operator<(const Point& p) const { return x != p.x ? x < p.x : y < p.y; }
    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return x != p.x || y != p.y; }
    Point rotate(ld theta) const { return Point(x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)); }
    friend R dot(const Point& p, const Point& q) { return p.x * q.x + p.y * q.y; }
    friend R cross(const Point& p, const Point& q) { return p.x * q.y - p.y * q.x; }
    friend R norm(const Point& p) { return dot(p, p); }
    friend ld abs(const Point& p) { return sqrt(norm(p)); }
    friend ld arg(const Point& p) { return atan2(p.y, p.x); }
    friend Point round(const Point& p) { return Point(round(p.x), round(p.y)); }
    friend istream& operator>>(istream& is, Point& p) { return is >> p.x >> p.y; }
    friend ostream& operator<<(ostream& os, const Point& p) { return os << p.x << " " << p.y; }
};

// 多角形
template <class R>
using Polygon = vector<Point<R>>;

// 凸多角形 C の内部に点 x があるか
// out: 0, on: 1, in: 2
template <class R>
int contains_convex(const Polygon<R>& C, const Point<R>& p) {
    int N = C.size();
    auto b1 = cross(C[1] - C[0], p - C[0]), b2 = cross(C[N - 1] - C[0], p - C[0]);
    if (b1 < -EPS || b2 > EPS) return 0;

    int left = 1, right = N - 1;
    while (right - left > 1) {
        int mid = (right + left) / 2;
        (cross(p - C[0], C[mid] - C[0]) >= 0 ? right : left) = mid;
    }
    auto v = cross(C[left] - p, C[right] - p);
    if (equals(v, 0)) {
        return 1;
    } else if (v > 0) {
        return (equals(b1, 0) || equals(b2, 0)) ? 1 : 2;
    }
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N;
    cin >> N;
    Polygon<ld> C(N);
    // 影の i 点目は 10^6 / (10^6 - 100) 倍の位置
    for (int i = 0; i < N; i++) {
        ld x, y;
        cin >> x >> y, x *= 10000, y *= 10000;
        C[i] = {x, y};
    }
    int Q;
    cin >> Q;
    while (Q--) {
        Point<ld> P;
        cin >> P, P.x *= 9999, P.y *= 9999;
        // C の内部に P があるかどうか判定
        cout << (contains_convex(C, P) == 2 ? 1 : 0) << '\n';
    }
}
accuracy: 1
time_ms: 30
memory_kb: 4352
final_rank: 1

code_snippet: // Nyaan 大先生いつもお世話になっております。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

using ld = long double;
constexpr ld EPS = 1e-10;
const ld PI = acos(-1);

bool equals(ld a, ld b) { return abs(b - a) < EPS; }
int sign(ld a) { return equals(a, 0) ? 0 : (a > 0 ? 1 : -1); }

template <class R>
struct Point {
    R x, y;
    Point() : x(0), y(0) {}
    template <class T, class U>
    Point(T x0, U y0) : x(x0), y(y0) {}
    template <class T, class U>
    Point(const pair<T, U>& p) : x(p.first), y(p.second) {}

    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point& p) const { return Point(*this) += p; }
    Point operator-(const Point& p) const { return Point(*this) -= p; }
    Point operator*(const R& k) const { return Point(*this) *= k; }
    Point operator/(const R& k) const { return Point(*this) /= k; }
    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point& operator*=(const R& k) {
        x *= k, y *= k;
        return *this;
    }
    Point& operator/=(const R& k) {
        x /= k, y /= k;
        return *this;
    }
    bool operator<(const Point& p) const { return x != p.x ? x < p.x : y < p.y; }
    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return x != p.x || y != p.y; }
    Point rotate(ld theta) const { return Point(x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)); }
    friend R dot(const Point& p, const Point& q) { return p.x * q.x + p.y * q.y; }
    friend R cross(const Point& p, const Point& q) { return p.x * q.y - p.y * q.x; }
    friend R norm(const Point& p) { return dot(p, p); }
    friend ld abs(const Point& p) { return sqrt(norm(p)); }
    friend ld arg(const Point& p) { return atan2(p.y, p.x); }
    friend Point round(const Point& p) { return Point(round(p.x), round(p.y)); }
    friend istream& operator>>(istream& is, Point& p) { return is >> p.x >> p.y; }
    friend ostream& operator<<(ostream& os, const Point& p) { return os << p.x << " " << p.y; }
};

// 多角形
template <class R>
using Polygon = vector<Point<R>>;

// 凸多角形 C の内部に点 x があるか
// out: 0, on: 1, in: 2
template <class R>
int contains_convex(const Polygon<R>& C, const Point<R>& p) {
    int N = C.size();
    auto b1 = cross(C[1] - C[0], p - C[0]), b2 = cross(C[N - 1] - C[0], p - C[0]);
    if (b1 < -EPS || b2 > EPS) return 0;

    int left = 1, right = N - 1;
    while (right - left > 1) {
        int mid = (right + left) / 2;
        (cross(p - C[0], C[mid] - C[0]) >= 0 ? right : left) = mid;
    }
    auto v = cross(C[left] - p, C[right] - p);
    if (equals(v, 0)) {
        return 1;
    } else if (v > 0) {
        return (equals(b1, 0) || equals(b2, 0)) ? 1 : 2;
    }
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N;
    cin >> N;
    Polygon<ld> C(N);
    // 影の i 点目は 10^6 / (10^6 - 100) 倍の位置
    for (int i = 0; i < N; i++) {
        int x, y;
        cin >> x >> y, x *= 10000, y *= 10000;
        C[i] = {x, y};
    }
    int Q;
    cin >> Q;
    while (Q--) {
        Point<ld> P;
        cin >> P, P.x *= 9999, P.y *= 9999;
        // C の内部に P があるかどうか判定
        cout << (contains_convex(C, P) == 2 ? 1 : 0) << '\n';
    }
}
accuracy: 0.18421052631578946
time_ms: 10
memory_kb: 3712
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug_print.hpp>
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (static_cast<void>(0))
#endif

using ld = long double;
constexpr ld EPS = 1e-10;
const ld PI = acos(-1);

bool equals(ld a, ld b) { return abs(b - a) < EPS; }
int sign(ld a) { return equals(a, 0) ? 0 : (a > 0 ? 1 : -1); }

template <class R>
struct Point {
    R x, y;
    Point() : x(0), y(0) {}
    Point(R x0, R y0) : x(x0), y(y0) {}
    template <class T, class U>
    Point(const pair<T, U>& p) : x(p.first), y(p.second) {}

    // 四則演算
    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point& p) const { return Point(*this) += p; }
    Point operator-(const Point& p) const { return Point(*this) -= p; }
    Point operator*(const R& k) const { return Point(*this) *= k; }
    Point operator/(const R& k) const { return Point(*this) /= k; }
    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point& operator*=(const R& k) {
        x *= k, y *= k;
        return *this;
    }
    Point& operator/=(const R& k) {
        x /= k, y /= k;
        return *this;
    }

    // 比較演算
    bool operator<(const Point& p) const { return x != p.x ? x < p.x : y < p.y; }
    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return !(*this == p); }

    Point rotate(ld theta) const { return Point(x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)); }
    friend R dot(const Point& p, const Point& q) { return p.x * q.x + p.y * q.y; }
    friend R cross(const Point& p, const Point& q) { return p.x * q.y - p.y * q.x; }
    friend R norm(const Point& p) { return dot(p, p); }
    friend ld abs(const Point& p) { return sqrt(norm(p)); }
    friend ld arg(const Point& p) { return atan2(p.y, p.x); }
    friend istream& operator>>(istream& is, Point& p) { return is >> p.x >> p.y; }
    friend ostream& operator<<(ostream& os, const Point& p) { return os << p.x << " " << p.y; }
};
// a - b - c の位置関係
template <class R>
int ccw(const Point<R>& a, const Point<R>& b, const Point<R>& c) {
    Point x = b - a, y = c - a;
    if (cross(x, y) > EPS) return +1;                 // a - b - c が反時計回り(a - b から見て c が左側)
    if (cross(x, y) < -EPS) return -1;                // a - b - c が時計回り(a - b から見て c が右側)
    if (min(norm(x), norm(y)) < EPS * EPS) return 0;  // c = a または c = b
    if (dot(x, y) < EPS) return +2;                   // c - a - b の順で一直線
    if (norm(x) < norm(y)) return -2;                 // a - b - c の順で一直線
    return 0;                                         // a - c - b の順で一直線
}
// 偏角ソート
template <class R>
void argument_sort(vector<Point<R>>& P) {
    // 領域が負にある場合 1, 領域が正にある場合 0
    auto sign = [&](const Point<R>& p) -> int { return p.y != 0 ? p.y < 0 : p.x > 0; };
    auto arg_cmp = [&](const Point<R>& a, const Point<R>& b) -> bool {
        return (sign(a) != sign(b) ? sign(a) > sign(b) : cross(a, b) != 0 ? cross(a, b) > 0 : norm(a) < norm(b));
    };
    sort(P.begin(), P.end(), arg_cmp);
}

// 多角形
template <class R>
using Polygon = vector<Point<R>>;

// 多角形 P の内部に点 x があるか: O(N) 時間
// out: 0, on: 1, in: 2
template <class R>
int contains_polygon(const Polygon<R>& P, const Point<R>& x) {
    bool in = false;
    for (int i = 0; i < (int)P.size(); i++) {
        Point a = P[i] - x, b = P[(i + 1) % P.size()] - x;
        if (a.y > b.y) swap(a, b);  // a.y < b.y
        if (sign(a.y) <= 0 && sign(b.y) > 0 && sign(cross(a, b)) < 0) in ^= 1;
        if (equals(cross(a, b), 0) && sign(dot(a, b)) <= 0) return 1;
    }
    return in ? 2 : 0;
}

// 凸多角形 C の内部に点 x があるか: O(log N) 時間
// out: 0, on: 1, in: 2
template <class R>
int contains_convex(const Polygon<R>& C, const Point<R>& p) {
    int N = C.size();
    auto b1 = cross(C[1] - C[0], p - C[0]), b2 = cross(C[N - 1] - C[0], p - C[0]);
    if (b1 < -EPS || b2 > EPS) return 0;

    int left = 1, right = N - 1;
    while (right - left > 1) {
        int mid = (right + left) / 2;
        (cross(p - C[0], C[mid] - C[0]) >= 0 ? right : left) = mid;
    }
    auto v = cross(C[left] - p, C[right] - p);
    if (equals(v, 0)) {
        return 1;
    } else if (v > 0) {
        return (equals(b1, 0) || equals(b2, 0)) ? 1 : 2;
    }
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N;
    cin >> N;
    Polygon<ld> P(N);
    for (int i = 0; i < N; i++) cin >> P[i];

    // 各点 (z = 100) と太陽 (x = y = 0, z = 10^6) を結ぶ直線と平面 (z = 0) の交点を求める
    // P0 := 影の凸多角形
    Polygon<ld> P0(N);
    for (int i = 0; i < N; i++) {
        Point<ld> p = P[i] * 1e6 / (1e6 - 100);
        P0[i] = p;
    }

    int Q;
    cin >> Q;
    while (Q--) {
        Point<ld> p;
        cin >> p;
        // 点 p が凸多角形 P0 の内部にあれば 1, 外部にあれば 0
        cout << (contains_convex(P0, p) == 2 ? 1 : 0) << '\n';
    }
}
accuracy: 1
time_ms: 40
memory_kb: 4992
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

#ifdef LOCAL
#include <debug_print.hpp>
#define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (static_cast<void>(0))
#endif

using ld = long double;
constexpr ld EPS = 1e-10;
const ld PI = acos(-1);

bool equals(ld a, ld b) { return abs(b - a) < EPS; }
int sign(ld a) { return equals(a, 0) ? 0 : (a > 0 ? 1 : -1); }

template <class R>
struct Point {
    R x, y;
    Point() : x(0), y(0) {}
    Point(R x0, R y0) : x(x0), y(y0) {}
    template <class T, class U>
    Point(const pair<T, U>& p) : x(p.first), y(p.second) {}

    // 四則演算
    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point& p) const { return Point(*this) += p; }
    Point operator-(const Point& p) const { return Point(*this) -= p; }
    Point operator*(const R& k) const { return Point(*this) *= k; }
    Point operator/(const R& k) const { return Point(*this) /= k; }
    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point& operator*=(const R& k) {
        x *= k, y *= k;
        return *this;
    }
    Point& operator/=(const R& k) {
        x /= k, y /= k;
        return *this;
    }

    // 比較演算
    bool operator<(const Point& p) const { return x != p.x ? x < p.x : y < p.y; }
    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return !(*this == p); }

    Point rotate(ld theta) const { return Point(x * cos(theta) - y * sin(theta), x * sin(theta) + y * cos(theta)); }
    friend R dot(const Point& p, const Point& q) { return p.x * q.x + p.y * q.y; }
    friend R cross(const Point& p, const Point& q) { return p.x * q.y - p.y * q.x; }
    friend R norm(const Point& p) { return dot(p, p); }
    friend ld abs(const Point& p) { return sqrt(norm(p)); }
    friend ld arg(const Point& p) { return atan2(p.y, p.x); }
    friend istream& operator>>(istream& is, Point& p) { return is >> p.x >> p.y; }
    friend ostream& operator<<(ostream& os, const Point& p) { return os << p.x << " " << p.y; }
};

template <class R>
int ccw(const Point<R>& a, const Point<R>& b, const Point<R>& c) {
    Point x = b - a, y = c - a;
    if (cross(x, y) > EPS) return +1;                 // a - b - c が反時計回り(a - b から見て c が左側)
    if (cross(x, y) < -EPS) return -1;                // a - b - c が時計回り(a - b から見て c が右側)
    if (min(norm(x), norm(y)) < EPS * EPS) return 0;  // c = a または c = b
    if (dot(x, y) < EPS) return +2;                   // c - a - b の順で一直線
    if (norm(x) < norm(y)) return -2;                 // a - b - c の順で一直線
    return 0;                                         // a - c - b の順で一直線
}

template <class R>
struct Line {
    Point<R> a, b;
    Line() = default;
    Line(const Point<R>& a0, const Point<R>& b0) : a(a0), b(b0) {}
    // Ax + By = C となる直線
    Line(const ld& A, const ld& B, const ld& C) {
        if (equals(A, 0)) {
            assert(!equals(B, 0));
            a = Point(0, C / B);
            b = Point(1, C / B);
        } else if (equals(B, 0)) {
            a = Point(C / A, 0);
            b = Point(C / A, 1);
        } else if (equals(C, 0)) {
            a = Point(0, C / B);
            b = Point(1, (C - A) / B);
        } else {
            a = Point(0, C / B);
            b = Point(C / A, 0);
        }
    }
    friend ostream& operator<<(ostream& os, const Line& l) { return os << l.a << " to " << l.b; }
    friend istream& operator>>(istream& is, Line& l) { return is >> l.a >> l.b; }
};

// 2 直線が平行かどうか
template <class R>
bool is_parallel(const Line<R>& a, const Line<R>& b) {
    return equals(cross(a.b - a.a, b.b - b.a), 0);
}
// 2 直線が直行かどうか
template <class R>
bool is_orthogonal(const Line<R>& a, const Line<R>& b) {
    return equals(dot(a.b - a.a, b.b - b.a), 0);
}
// 直線 l に頂点 p から垂線を下ろした交点(射影)
template <class R>
Point<R> projection(const Line<R>& l, const Point<R>& p) {
    ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
// 直線 l を軸に点 p と線対称な点(反射)
template <class R>
Point<R> reflection(const Line<R>& l, const Point<R>& p) {
    return (projection(l, p)) * 2 - p;
}

// 線分 (直線の継承)
template <class R>
struct Segment : Line<R> {
    Segment() = default;
};

// 線分 s に点 p が乗っているか
template <class R>
bool is_intersect_sp(const Segment<R>& s, const Point<R>& p) {
    return ccw(s.a, s.b, p) == 0;
}
// 線分 s と線分 t が交差しているか
template <class R>
bool is_intersect_ss(const Segment<R>& s, const Segment<R>& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
// 線分 s と点 p の距離
template <class R>
ld distance_sp(const Segment<R>& s, const Point<R>& p) {
    Point r = projection(s, p);
    if (is_intersect_sp(s, r)) return abs(r - p);
    return min(abs(s.a - p), abs(s.b - p));
}
// 線分 s と線分 t の距離
template <class R>
ld distance_ss(const Segment<R>& s, const Segment<R>& t) {
    if (is_intersect_ss(s, t)) return 0;
    return min({distance_sp(s, t.a), distance_sp(s, t.b), distance_sp(t, s.a), distance_sp(t, s.b)});
}
// 直線 / 線分 a, b の交点
template <class R>
Point<R> cross_point(const Line<R>& a, const Line<R>& b) {
    ld A = cross(a.b - a.a, b.b - b.a);
    ld B = cross(a.b - a.a, a.b - b.a);
    if (equals(A, 0) && equals(B, 0)) return b.a;
    return b.a + (b.b - b.a) * B / A;
}
// 偏角ソート
template <class R>
void argument_sort(vector<Point<R>>& P) {
    // 領域が負にある場合 1, 領域が正にある場合 0
    auto sign = [&](const Point<R>& p) -> int { return p.y != 0 ? p.y < 0 : p.x > 0; };
    auto arg_cmp = [&](const Point<R>& a, const Point<R>& b) -> bool {
        return (sign(a) != sign(b) ? sign(a) > sign(b) : cross(a, b) != 0 ? cross(a, b) > 0 : norm(a) < norm(b));
    };
    sort(P.begin(), P.end(), arg_cmp);
}

// 多角形
template <class R>
using Polygon = vector<Point<R>>;

// 多角形の面積
template <class R>
ld area(const Polygon<R>& P) {
    ld res = 0;
    for (int i = 0; i < (int)P.size(); i++) {
        res += cross(P[i], P[(i + 1) % P.size()]);
    }
    return abs(res) / 2;
}

// 多角形 P の内部に点 x があるか
// out: 0, on: 1, in: 2
template <class R>
int contains_polygon(const Polygon<R>& P, const Point<R>& x) {
    bool in = false;
    for (int i = 0; i < (int)P.size(); i++) {
        Point a = P[i] - x, b = P[(i + 1) % P.size()] - x;
        if (a.y > b.y) swap(a, b);  // a.y < b.y
        if (sign(a.y) <= 0 && sign(b.y) > 0 && sign(cross(a, b)) < 0) in ^= 1;
        if (equals(cross(a, b), 0) && sign(dot(a, b)) <= 0) return 1;
    }
    return in ? 2 : 0;
}

// 頂点集合から凸包を構築
// boundary = true なら凸包の境界上の点も含む
template <class R, bool boundary = false>
Polygon<R> convex_hull(vector<Point<R>> ps) {
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    int N = ps.size(), k = 0;
    if (N <= 2) return ps;
    Polygon<R> ch(2 * N);
    // 反時計回り
    ld th = boundary ? -EPS : EPS;
    for (int i = 0; i < N; ch[k++] = ps[i++]) {
        while (k >= 2 && cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1]) < th) --k;
    }
    for (int i = N - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) {
        while (k >= t && cross(ch[k - 1] - ch[k - 2], ps[i] - ch[k - 1]) < th) --k;
    }
    ch.resize(k - 1);
    return ch;
}

// 凸多角形の最遠点対
template <class R>
pair<int, int> convex_polygon_diameter(const Polygon<R>& P) {
    int N = P.size();
    int is = 0, js = 0;
    for (int i = 0; i < N; i++) {
        if (P[i].y > P[is].y) is = i;
        if (P[i].y < P[js].y) js = i;
    }
    R max_dist = norm(P[is] - P[js]);
    int i = is, max_i = is, j = js, max_j = js;
    do {
        if (cross(P[(i + 1) % N] - P[i], P[(j + 1) % N] - P[j]) >= 0) {
            j = (j + 1) % N;
        } else {
            i = (i + 1) % N;
        }
        if (norm(P[i] - P[j]) > max_dist) {
            max_dist = norm(P[i] - P[j]), max_i = i, max_j = j;
        }
    } while (i != is || j != js);
    return minmax(max_i, max_j);
}

// 凸包を直線で切ったときの片方 (直線 a -> b の進行方向左側) を返す
template <class R>
Polygon<R> convex_polygon_cut(const Polygon<R>& P, const Line<R>& l) {
    int N = P.size();
    Polygon<R> res;
    for (int i = 0; i < N; i++) {
        const Point<R>&x = P[i], y = P[(i + 1) % N];
        auto cf = cross(l.a - x, l.b - x), cs = cross(l.a - y, l.b - y);
        if (sign(cf) >= 0) res.emplace_back(x);
        if (sign(cf) * sign(cs) < 0) res.emplace_back(cross_point(Line(x, y), l));
    }
    return res;
}

// 凸多角形 C の内部に点 x があるか
// out: 0, on: 1, in: 2
template <class R>
int contains_convex(const Polygon<R>& C, const Point<R>& p) {
    int N = C.size();
    auto b1 = cross(C[1] - C[0], p - C[0]), b2 = cross(C[N - 1] - C[0], p - C[0]);
    if (b1 < -EPS || b2 > EPS) return 0;

    int left = 1, right = N - 1;
    while (right - left > 1) {
        int mid = (right + left) / 2;
        (cross(p - C[0], C[mid] - C[0]) >= 0 ? right : left) = mid;
    }
    auto v = cross(C[left] - p, C[right] - p);
    if (equals(v, 0)) {
        return 1;
    } else if (v > 0) {
        return (equals(b1, 0) || equals(b2, 0)) ? 1 : 2;
    }
    return 0;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N;
    cin >> N;
    Polygon<ld> P(N);
    for (int i = 0; i < N; i++) cin >> P[i];

    // 各点 (z = 100) と太陽 (x = y = 0, z = 10^6) を結ぶ直線と平面 (z = 0) の交点を求める
    Polygon<ld> P0(N);
    for (int i = 0; i < N; i++) {
        Point<ld> p = P[i] * 1e6 / (1e6 - 100);
        P0[i] = p;
    }

    int Q;
    cin >> Q;
    while (Q--) {
        Point<ld> p;
        cin >> p;
        // 点 p が凸多角形 P0 の内部にあれば 1, 外部にあれば 0
        cout << (contains_convex(P0, p) == 2 ? 1 : 0) << '\n';
    }
}
accuracy: 1
time_ms: 40
memory_kb: 4856
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

using i64 = long long;
#define rep(i, a, b) for (int i = a; i < b; i++)


struct Point {
    double x, y;
    Point() = default;
    Point(double x_, double y_) : x(x_), y(y_) {}
    friend Point operator+(const Point &l, const Point &r) {
        return Point(l.x + r.x, l.y + r.y);
    }
    friend Point operator-(const Point &l, const Point &r) {
        return Point(l.x - r.x, l.y - r.y);
    }
};

int main() {
    int n;
    cin >> n;
    vector<Point> t(n);
    rep (i, 0, n) {
        cin >> t[i].x >> t[i].y;
        t[i].x *= double(1e6) / (1e6 - 100);
        t[i].y *= double(1e6) / (1e6 - 100);
    }

    auto cross = [&](Point a, Point b) -> double {
        return a.x * b.y - a.y * b.x;
    };

    sort(begin(t), end(t), [&](Point x, Point y) -> bool {
        if (x.x != y.x) return x.x < y.x;
        return x.y < y.y;
    });

    vector<Point> up, down;
    up.push_back(t[0]);
    up.push_back(t[1]);
    down.push_back(t[0]);
    down.push_back(t[1]);

    rep (i, 2, n) {
        while ((int)up.size() >= 2 and
            cross(up[up.size() - 1] - up[up.size() - 2],
                  t[i] - up[up.size() - 1])
                >= 0) {
            up.pop_back();
        }
        while ((int)down.size() >= 2 and
            cross(down[down.size() - 1] - down[down.size() - 2],
                  t[i] - down[down.size() - 1])
                <= 0) {
            down.pop_back();
        }
        up.push_back(t[i]);
        down.push_back(t[i]);
    }

    // cout << "up" << endl;
    // for (auto p : up) {
    //     cout << p.x << " " << p.y << endl;
    // }
    // cout << "down" << endl;
    // for (auto p : down) {
    //     cout << p.x << " " << p.y << endl;
    // }

    int q;
    cin >> q;
    vector<pair<Point, int>> ps(q);
    rep (i, 0, q) {
        cin >> ps[i].first.x >> ps[i].first.y;
        ps[i].second = i;
    }
    sort(begin(ps), end(ps), [&](auto x, auto y) -> bool {
        if (x.first.x != y.first.x) return x.first.x < y.first.x;
        return x.first.y < y.first.y;
    });

    vector<int> res(q);
    int nowup = -1, nowdown = -1;
    rep (i, 0, q) {
        while (nowup < (int)up.size() - 1 and ps[i].first.x > up[nowup + 1].x) ++nowup;
        while (nowdown < (int)down.size() - 1 and ps[i].first.x > down[nowdown + 1].x) ++nowdown;
        // cout << ps[i].second << endl;
        // cout << nowup << " " << nowdown << endl;
        if (nowup == -1 or nowup == up.size() - 1 or
                nowdown == -1 or nowdown == down.size() - 1) {
            res[ps[i].second] = 0;
            continue;
        }

        if (cross(up[nowup + 1] - up[nowup], ps[i].first - up[nowup]) < 0 and
                cross(down[nowdown + 1] - down[nowdown], ps[i].first - down[nowdown]) > 0) {
            res[ps[i].second] = 1;
        }
        else res[ps[i].second] = 0;
    }

    rep (i, 0, q) cout << res[i] << endl;

    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 5788
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<pair<long double,long double>> a(n,pair<long double,long double>());
	for(int i = 0;i < n;i++){
		cin >> a[i].first >> a[i].second;
	}
	a.push_back(a[0]);
	vector<vector<pair<pair<int,int>,int>>> t(2);
	for(int i = 0;i < n;i++){
		if(a[i].second < a[i + 1].second){
			t[0].push_back({{a[i].second,a[i + 1].second},i});
		}else{
			t[1].push_back({{a[i + 1].second,a[i].second},i});
		}
	}
	sort(t[0].begin(),t[0].end());
	sort(t[1].begin(),t[1].end());
	int Q;
	cin >> Q;
	for(int i = 0;i < Q;i++){
		pair<long double,long double> p;
		cin >> p.first >> p.second;
		p.first *= (long double)(999900) / (long double)(1000000);
		p.second *= (long double)(999900) / (long double)(1000000);
		if(p.second < t[0][0].first.first || t[0].back().first.second < p.second){
			cout << 0 << endl;
			continue;
		}
		pair<int,int> it;
		{
			int low = 0,high = (int)t[0].size() - 1;
			while(low < high){
				int mid = (low + high + 1) / 2;
				if(t[0][mid].first.first <= p.second){
					low = mid;
				}else{
					high = mid - 1;
				}
			}
			it.first = t[0][low].second;
		}
		{
			int low = 0,high = (int)t[1].size() - 1;
			while(low < high){
				int mid = (low + high + 1) / 2;
				if(t[1][mid].first.first <= p.second){
					low = mid;
				}else{
					high = mid - 1;
				}
			}
			it.second = t[1][low].second;
		}
		pair<long double,long double> r;
		if(a[it.first].second == a[it.first + 1].second){
			r.first = a[it.first].first;
		}else{
			r.first = a[it.first].first + (a[it.first + 1].first - a[it.first].first) * (p.second - a[it.first].second) / (a[it.first + 1].second - a[it.first].second);
		}
		if(a[it.second].second == a[it.second + 1].second){
			r.second = a[it.second].first;
		}else{
			r.second = a[it.second].first + (a[it.second + 1].first - a[it.second].first) * (p.second - a[it.second].second) / (a[it.second + 1].second - a[it.second].second);
		}
		if(min(r.first,r.second) <= p.first && p.first <= max(r.first,r.second)){
			cout << 1 << endl;
		}else{
			cout << 0 << endl;
		}
	}
}
accuracy: 1
time_ms: 100
memory_kb: 5024
final_rank: 9

code_snippet: // #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0412"
// 
// #include <iostream>
// 
// #include "geometry/contain.hpp"
// 
// int main() {
//     int N;
//     std::cin >> N;
//     Polygon<double> q(N);
//     std::cin >> q;
//     for (int i = 0; i < N; i++) q[i] *= 1e6 / (1e6 - 1e2);
//     int Q;
//     std::cin >> Q;
//     for (int i = 0; i < Q; i++) {
//         Point<double> p;
//         std::cin >> p;
//         auto res = convex_contain(q, p);
//         if (res == Contain::IN) {
//             std::cout << "1\n";
//         } else if (res == Contain::OUT) {
//             std::cout << "0\n";
//         } else {
//             assert(0);
//         }
//     }
//     return 0;
// }
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0412"

#include <iostream>

#include <type_traits>

// Constants (EPS, PI)
// EPS の変更は Constants<T>::set_eps(new_eps) で
template <class T> struct Constants {
    static T EPS;
    static void set_eps(const T e) { EPS = e; }
    static constexpr T PI = 3.14159'26535'89793L;
};

template <> double Constants<double>::EPS = 1e-9;
template <> long double Constants<long double>::EPS = 1e-12;
template <> long long Constants<long long>::EPS = 0;

// 汎用関数
template <class T> inline int sign(const T x) { return x < -Constants<T>::EPS ? -1 : (x > Constants<T>::EPS ? 1 : 0); }
template <class T> inline bool equal(const T a, const T b) { return sign(a - b) == 0; }
template <class T> inline T radian_to_degree(const T r) { return r * 180.0 / Constants<T>::PI; }
template <class T> inline T degree_to_radian(const T d) { return d * Constants<T>::PI / 180.0; }

// type traits
template <class T> using is_geometry_floating_point = typename std::conditional<std::is_same<T, double>::value || std::is_same<T, long double>::value, std::true_type, std::false_type>::type;
template <class T> using is_geometry_integer = typename std::conditional<std::is_same<T, long long>::value, std::true_type, std::false_type>::type;
template <class T> using is_geometry = typename std::conditional<is_geometry_floating_point<T>::value || is_geometry_integer<T>::value, std::true_type, std::false_type>::type;

#include <cmath>
#include <cassert>

// 点
template <class T> struct Point {
    T x, y;

    Point() = default;
    Point(const T x, const T y) : x(x), y(y) {}

    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point& operator*=(const Point& p) {
        static_assert(is_geometry_floating_point<T>::value == true);
        return *this = Point(x * p.x - y * p.y, x * p.y + y * p.x);
    }
    Point& operator/=(const Point& p) {
        static_assert(is_geometry_floating_point<T>::value == true);
        return *this = Point(x * p.x + y * p.y, -x * p.y + y * p.x) / (p.x * p.x + p.y * p.y);
    }
    Point& operator*=(const T k) {
        x *= k, y *= k;
        return *this;
    }
    Point& operator/=(const T k) {
        static_assert(is_geometry_floating_point<T>::value == true);
        x /= k, y /= k;
        return *this;
    }

    Point operator+() const { return *this; }
    Point operator-() const { return Point(-x, -y); }

    friend Point operator+(const Point& a, const Point& b) { return Point(a) += b; }
    friend Point operator-(const Point& a, const Point& b) { return Point(a) -= b; }
    friend Point operator*(const Point& a, const Point& b) { return Point(a) *= b; }
    friend Point operator/(const Point& a, const Point& b) { return Point(a) /= b; }
    friend Point operator*(const Point& p, const T k) { return Point(p) *= k; }
    friend Point operator/(const Point& p, const T k) { return Point(p) /= k; }

    // 辞書式順序
    friend bool operator<(const Point& a, const Point& b) { return a.x == b.x ? a.y < b.y : a.x < b.x; }
    friend bool operator>(const Point& a, const Point& b) { return a.x == b.x ? a.y > b.y : a.x > b.x; }
    friend bool operator==(const Point& a, const Point& b) { return a.x == b.x and a.y == b.y; }

    // I/O
    friend std::istream& operator>>(std::istream& is, Point& p) { return is >> p.x >> p.y; }
    friend std::ostream& operator<<(std::ostream& os, const Point& p) { return os << '(' << p.x << ' ' << p.y << ')'; }
};

// 汎用関数
// 点の一致判定
template <class T> inline bool equal(const Point<T>& a, const Point<T>& b) { return equal(a.x, b.x) and equal(a.y, b.y); }
// 内積
template <class T> inline T dot(const Point<T>& a, const Point<T>& b) { return a.x * b.x + a.y * b.y; }
// 外積
template <class T> inline T cross(const Point<T>& a, const Point<T>& b) { return a.x * b.y - a.y * b.x; }
// rad ラジアンだけ反時計回りに回転
template <class T> inline Point<T> rotate(const Point<T>& p, const T theta) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return p * Point<T>(std::cos(theta), std::sin(theta));
}
// (x, y) の辞書式順序 (誤差許容)
template <class T> inline bool compare_x(const Point<T>& a, const Point<T>& b) { return equal(a.x, b.x) ? sign(a.y - b.y) < 0 : sign(a.x - b.x) < 0; }
// (y, x) の辞書式順序 (誤差許容)
template <class T> inline bool compare_y(const Point<T>& a, const Point<T>& b) { return equal(a.y, b.y) ? sign(a.x - b.x) < 0 : sign(a.y - b.y) < 0; }
// 整数のまま行う偏角ソート
// 無限の精度をもつ arg(p) = atan2(y, x) で比較し, 同じ場合は norm(p) で比較 (atan2(0, 0) = 0 とする)
// 基本的に (-PI, PI] でソートされ, 点 (0, 0) は (-PI, 0) と [0, PI] の間に入る
// https://ngtkana.hatenablog.com/entry/2021/11/13/202103
// https://judge.yosupo.jp/problem/sort_points_by_argument
template <class T> inline bool compare_atan2(const Point<T>& a, const Point<T>& b) {
    static_assert(is_geometry_integer<T>::value == true);
    if ((Point<T>(a.y, -a.x) > Point<T>(0, 0)) == (Point<T>(b.y, -b.x) > Point<T>(0, 0))) {  // a, b in (-PI, 0] or a, b in (0, PI]
        if (a.x * b.y != a.y * b.x) return a.x * b.y > a.y * b.x;                            // cross(a, b) != 0
        return a == Point<T>(0, 0) ? b.x > 0 and b.y == 0 : (b == Point<T>(0, 0) ? a.y < 0 : norm(a) < norm(b));
    }
    return Point<T>(a.y, -a.x) < Point<T>(b.y, -b.x);
}
// 絶対値の 2 乗
template <class T> inline T norm(const Point<T>& p) { return p.x * p.x + p.y * p.y; }
// 絶対値
template <class T> inline T abs(const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return std::sqrt(norm(p));
}
// 偏角
template <class T> inline T arg(const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return std::atan2(p.y, p.x);  // (-PI, PI]
}
// 共役複素数 (x 軸について対象な点)
template <class T> inline Point<T> conj(const Point<T>& p) { return Point(p.x, -p.y); }
// 極座標系 -> 直交座標系 (絶対値が rho で偏角が theta ラジアン)
template <class T> inline Point<T> polar(const T rho, const T theta = T(0)) {
    static_assert(is_geometry_floating_point<T>::value == true);
    assert(sign(rho) >= 0);
    return Point<T>(std::cos(theta), std::sin(theta)) * rho;
}
// ccw の戻り値
enum class Ccw {
    COUNTER_CLOCKWISE = 1,  // a->b->c 反時計回り
    CLOCKWISE = -1,         // a->b->c 時計回り
    ONLINE_BACK = 2,        // c->a->b 直線
    ONLINE_FRONT = -2,      // a->b->c 直線
    ON_SEGMENT = 0          // a->c->b 直線
};
// 点 a, b, c の位置関係
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
template <class T> Ccw ccw(const Point<T>& a, const Point<T>& b, const Point<T>& c) {
    Point<T> ab = b - a;
    Point<T> ac = c - a;
    if (sign(cross(ab, ac)) == 1) return Ccw::COUNTER_CLOCKWISE;
    if (sign(cross(ab, ac)) == -1) return Ccw::CLOCKWISE;
    if (sign(dot(ab, ac)) == -1) return Ccw::ONLINE_BACK;
    if (sign(norm(ab) - norm(ac)) == -1) return Ccw::ONLINE_FRONT;
    return Ccw::ON_SEGMENT;
}
// 線分 a -> b から 線分 a -> c までの角度 (ラジアンで -PI より大きく PI 以下)
template <class T> T get_angle(const Point<T>& a, const Point<T>& b, const Point<T>& c) {
    Point<T> ab = b - a;
    Point<T> ac = c - a;
    // a-bが x 軸になるように回転
    ac *= conj(ab) / norm(ab);
    return arg(ac);  // (-PI, PI]
}

#include <vector>

// 多角形
template <class T> using Polygon = std::vector<Point<T>>;
template <class T> std::istream& operator>>(std::istream& is, Polygon<T>& p) {
    for (auto&& pi : p) is >> pi;
    return is;
}
template <class T> std::ostream& operator<<(std::ostream& os, const Polygon<T>& p) {
    for (auto&& pi : p) os << pi << " -> ";
    return os;
}

// 多角形の面積 (符号付き)
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
// return area * 2
template <class T> T area2(const Polygon<T>& p) {
    const int n = (int)(p.size());
    assert(n >= 2);
    T res = T(0);
    for (int i = 0; i < n; i++) res += cross(p[i], p[i + 1 == n ? 0 : i + 1]);
    // counter clockwise: res > 0
    // clockwise: res < 0
    return res;
}
template <class T> T area(const Polygon<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return area2(p) / T(2);
}

// 多角形の凸判定 (角度が 0 でも PI でも許容)
// 許容したくないときには ON_SEGMENT, ONLINE_FRONT, ONLINE_BACK が出てきたら false を返せば OK
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
template <class T> bool is_convex(const Polygon<T>& p) {
    const int n = (int)(p.size());
    assert(n >= 3);
    bool okccw = true, okcw = true;
    for (int i = 0; i < n; i++) {
        auto res = ccw(p[i], p[i + 1 >= n ? i + 1 - n : i + 1], p[i + 2 >= n ? i + 2 - n : i + 2]);
        if (res == Ccw::CLOCKWISE) okccw = false;
        if (res == Ccw::COUNTER_CLOCKWISE) okcw = false;
        if (!okccw and !okcw) return false;
    }
    return true;
}

// 直線
template <class T> struct Line {
    Point<T> a, b;

    Line() = default;
    Line(const Point<T>& a, const Point<T>& b) : a(a), b(b) {}

    // Ax + By = C
    Line(const T A, const T B, const T C) {
        static_assert(is_geometry_floating_point<T>::value == true);
        assert(!(equal(A, T(0)) and equal(B, T(0))));
        if (equal(A, T(0))) {
            a = Point<T>(T(0), C / B), b = Point<T>(T(1), C / B);
        } else if (equal(B, T(0))) {
            a = Point<T>(C / A, T(0)), b = Point<T>(C / A, T(1));
        } else if (equal(C, T(0))) {
            a = Point<T>(T(0), T(0)), b = Point<T>(T(1), -A / B);
        } else {
            a = Point<T>(T(0), C / B), b = Point<T>(C / A, T(0));
        }
    }

    friend std::istream& operator>>(std::istream& is, Line& p) { return is >> p.a >> p.b; }
    friend std::ostream& operator<<(std::ostream& os, const Line& p) { return os << p.a << "->" << p.b; }
};

// 線分
template <class T> struct Segment : Line<T> {
    Segment() = default;

    Segment(const Point<T>& a, const Point<T>& b) : Line<T>(a, b) {}
};

// 点 p から直線 l に下ろした垂線と直線 l の交点
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
template <class T> Point<T> projection(const Line<T>& l, const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    T t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return l.a + (l.b - l.a) * t;
}

// 直線 l に関して点 p と対象な位置にある点
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
template <class T> Point<T> reflection(const Line<T>& l, const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return p + (projection(l, p) - p) * T(2);
}

// 直線 l1, l2 の垂直判定
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
template <class T> inline bool is_orthogonal(const Line<T>& l1, const Line<T>& l2) { return sign(dot(l1.b - l1.a, l2.b - l2.a)) == 0; }

// 直線 l1, l2 の平行判定
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
template <class T> inline bool is_parallel(const Line<T>& l1, const Line<T>& l2) { return sign(cross(l1.b - l1.a, l2.b - l2.a)) == 0; }

// 円
template <class T> struct Circle {
    Point<T> o;
    T r;

    Circle() = default;
    Circle(const Point<T>& o, const T r) : o(o), r(r) {}

    friend std::istream& operator>>(std::istream& is, Circle& c) { return is >> c.o >> c.r; }
    friend std::ostream& operator<<(std::ostream& os, const Circle& c) { return os << c.o << ", " << c.r; }
};

// 共通接線の本数
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A
template <class T> int tangent_number(Circle<T> c1, Circle<T> c2) {
    if (c1.r < c2.r) std::swap(c1, c2);
    const T d2 = norm(c1.o - c2.o);
    if (sign(d2 - (c1.r + c2.r) * (c1.r + c2.r)) == 1) return 4;  // d > c1.r + c2.r and c1.r + c2.r >= 0 <=> d ^ 2 > (c1.r + c2.r) ^ 2
    if (sign(d2 - (c1.r + c2.r) * (c1.r + c2.r)) == 0) return 3;  // d = c1.r + c2.r and c1.r + c2.r >= 0 <=> d ^ 2 = (c1.r + c2.r) ^ 2
    if (sign(d2 - (c1.r - c2.r) * (c1.r - c2.r)) == 1) return 2;  // d > c1.r - c2.r and c1.r - c2.r >= 0 <=> d ^ 2 > (c1.r - c2.r) ^ 2
    if (sign(d2 - (c1.r - c2.r) * (c1.r - c2.r)) == 0) return 1;  // d = c1.r - c2.r and c1.r - c2.r >= 0 <=> d ^ 2 = (c1.r - c2.r) ^ 2
    return 0;
}

// 交差判定 (直線, 線分, 円, 点)
// 直線 l1, l2 の交差判定
template <class T> bool is_intersect(const Line<T>& l1, const Line<T>& l2) {
    Point<T> base = l1.b - l1.a;
    T d12 = cross(base, l2.b - l2.a);
    T d1 = cross(base, l1.b - l2.a);
    // sign(d12) != 0 -> 平行でないので交差する
    // sign(d12) == 0 and sign(d1) == 0 -> 一致するので交差する
    return sign(d12) != 0 or sign(d1) == 0;
}
// 直線 l, 点 p の交差判定
template <class T> inline bool is_intersect(const Line<T>& l, const Point<T>& p) {
    auto res = ccw(l.a, l.b, p);
    return res == Ccw::ONLINE_BACK or res == Ccw::ONLINE_FRONT or res == Ccw::ON_SEGMENT;
}
template <class T> bool is_intersect(const Point<T>& p, const Line<T>& l) { return is_intersect(l, p); }

// 線分 s, 点 p の交差判定
template <class T> inline bool is_intersect(const Segment<T>& s, const Point<T>& p) { return ccw(s.a, s.b, p) == Ccw::ON_SEGMENT; }
template <class T> inline bool is_intersect(const Point<T>& p, const Segment<T>& s) { return ccw(s.a, s.b, p) == Ccw::ON_SEGMENT; }

// 直線 l, 線分 s の交差判定
template <class T> bool is_intersect(const Line<T>& l, const Segment<T>& s) {
    // s.a と s.b が直線 l に関して同じ側 (直線上を除き) にある場合に限り交差しない
    auto c1 = ccw(l.a, l.b, s.a);
    auto c2 = ccw(l.a, l.b, s.b);
    return !((c1 == c2) and (c1 == Ccw::CLOCKWISE or c1 == Ccw::COUNTER_CLOCKWISE));
}
template <class T> bool is_intersect(const Segment<T>& s, const Line<T>& l) { return is_intersect(l, s); }

// 線分 s1, s2 の交差判定
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
template <class T> inline bool is_intersect(const Segment<T>& s1, const Segment<T>& s2) {
    auto c1 = ccw(s1.a, s1.b, s2.a);
    auto c2 = ccw(s1.a, s1.b, s2.b);
    auto c3 = ccw(s2.a, s2.b, s1.a);
    auto c4 = ccw(s2.a, s2.b, s1.b);
    // 平行な場合: 重なるなら 1 次元で考えると必ず端点のどれかがもう一方の線分上にある
    if (c1 == Ccw::ON_SEGMENT or c2 == Ccw::ON_SEGMENT or c3 == Ccw::ON_SEGMENT or c4 == Ccw::ON_SEGMENT) return true;
    // 平行でない場合: 一方の線分の両側にもう一方の線分の端点がある, を線分を入れ替えても成立
    // 平行だが重ならない場合は以下の条件は成立しない
    bool ok1 = ((c1 == Ccw::CLOCKWISE and c2 == Ccw::COUNTER_CLOCKWISE) or (c1 == Ccw::COUNTER_CLOCKWISE and c2 == Ccw::CLOCKWISE));
    bool ok2 = ((c3 == Ccw::CLOCKWISE and c4 == Ccw::COUNTER_CLOCKWISE) or (c3 == Ccw::COUNTER_CLOCKWISE and c4 == Ccw::CLOCKWISE));
    return ok1 and ok2;
}

// 点 p1, p2 の交差判定
template <class T> inline bool is_intersect(const Point<T>& p1, const Point<T>& p2) { return equal(p1, p2); }

// 円 c1, c2 の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c1, const Circle<T>& c2) {
    const int num = tangent_number(c1, c2);
    return 1 <= num and num <= 3;
}

// 円 c, 点 p の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c, const Point<T>& p) { return equal(norm(p - c.o), c.r * c.r); }
template <class T> inline bool is_intersect(const Point<T>& p, const Circle<T>& c) { return equal(norm(p - c.o), c.r * c.r); }

// 円 c, 直線 l の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c, const Line<T>& l) {
    static_assert(is_geometry_floating_point<T>::value == true);
    // norm(c.o - projection(l, c.o)) が直線 l と 円 c の中心 c.o の距離の 2 乗
    return sign(c.r * c.r - norm(c.o - projection(l, c.o))) >= 0;
}
template <class T> inline bool is_intersect(const Line<T>& l, const Circle<T>& c) { return is_intersect(c, l); }

// 円 c, 線分 s の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c, const Segment<T>& s) {
    static_assert(is_geometry_floating_point<T>::value == true);
    if (!is_intersect(c, Line(s.a, s.b))) return false;  // 直線としても交差しない
    T d1 = abs(c.o - s.a), d2 = abs(c.o - s.b);
    if (sign(d1 - c.r) == -1 and sign(d2 - c.r) == -1) return false;  // 端点がどちらも円の内側
    if (sign(d1 - c.r) * sign(d2 - c.r) <= 0) return true;            // 円周をまたいでいる
    const Point<T> h = projection(s, c.o);
    return ccw(s.a, s.b, h) == Ccw::ON_SEGMENT;  // s.a -> h -> s.b の順で並んでいる
}
template <class T> inline bool is_intersect(const Segment<T>& s, const Circle<T>& c) { return is_intersect(c, s); }

enum class Contain { IN, ON, OUT };

// 円 c と点 p の位置関係
template <class T> Contain contain(const Circle<T>& c, const Point<T>& p) {
    int sgn = sign(norm(p - c.o) - c.r * c.r);
    return sgn == 1 ? Contain::OUT : (sgn == 0 ? Contain::ON : Contain::IN);
}

// 多角形 (凸とは限らない) q と点 p の位置関係
// 頂点は反時計回りに並んでいる
// O(n)
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
template <class T> Contain contain(const Polygon<T>& q, const Point<T>& p) {
    const int n = (int)(q.size());
    assert(n >= 3);
    bool x = false;
    for (int i = 0; i < n; i++) {
        if (is_intersect(Segment(q[i], q[(i + 1) % n]), p)) return Contain::ON;
        Point a = q[i] - p, b = q[(i + 1) % n] - p;
        if (a.y > b.y) std::swap(a, b);
        // a.y < b.y
        // check each point's y is 0 at most 1 times
        if (sign(a.y) <= 0 and sign(b.y) > 0 and sign(cross(a, b)) > 0) x = !x;
    }
    return (x ? Contain::IN : Contain::OUT);
}

// 凸多角形 (すべての内角が 180° 未満) q と点 p の位置関係
// 頂点は反時計回りに並んでいる
// O(log n)
// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0412
// https://atcoder.jp/contests/abc296/tasks/abc296_g
template <class T> Contain convex_contain(const Polygon<T>& q, const Point<T>& p) {
    const int n = (int)(q.size());
    assert(n >= 3);
    auto c1 = ccw(q[0], q[1], p);
    auto c2 = ccw(q[0], q[n - 1], p);
    if (c1 == Ccw::CLOCKWISE or c2 == Ccw::COUNTER_CLOCKWISE) return Contain::OUT;
    if (c1 == Ccw::ON_SEGMENT or c2 == Ccw::ON_SEGMENT) return Contain::ON;
    if (c1 == Ccw::ONLINE_FRONT or c2 == Ccw::ONLINE_FRONT) return Contain::OUT;
    // 二分探索 (q[0] -> q[i] -> p が反時計回りになるような最大の i)
    int ok = 1, ng = n - 1;
    while (ng - ok > 1) {
        int md = (ok + ng) / 2;
        if (ccw(q[0], q[md], p) == Ccw::COUNTER_CLOCKWISE) {
            ok = md;
        } else {
            ng = md;
        }
    }
    // 直線 q[ok] -> q[ok + 1] を基準に考える
    auto c3 = ccw(q[ok], q[ok + 1], p);
    assert(c3 != Ccw::ONLINE_FRONT);
    assert(c3 != Ccw::ONLINE_BACK);
    return c3 == Ccw::ON_SEGMENT ? Contain::ON : (c3 == Ccw::COUNTER_CLOCKWISE ? Contain::IN : Contain::OUT);
}

int main() {
    int N;
    std::cin >> N;
    Polygon<double> q(N);
    std::cin >> q;
    for (int i = 0; i < N; i++) q[i] *= 1e6 / (1e6 - 1e2);
    int Q;
    std::cin >> Q;
    for (int i = 0; i < Q; i++) {
        Point<double> p;
        std::cin >> p;
        auto res = convex_contain(q, p);
        if (res == Contain::IN) {
            std::cout << "1\n";
        } else if (res == Contain::OUT) {
            std::cout << "0\n";
        } else {
            assert(0);
        }
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3640
final_rank: 8

code_snippet: // #define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0412"
// 
// #include <iostream>
// 
// #include "geometry/convex_hull_monotone_chain.hpp"
// #include "geometry/contain.hpp"
// 
// int main() {
//     int N;
//     std::cin >> N;
//     Polygon<long double> q(N);
//     std::cin >> q;
//     q = convex_hull_monotone_chain(q, true);
//     for (int i = 0; i < N; i++) q[i] *= 1e6 / (1e6 - 1e2);
//     int Q;
//     std::cin >> Q;
//     for (int i = 0; i < Q; i++) {
//         Point<long double> p;
//         std::cin >> p;
//         auto res = convex_contain(q, p);
//         if (res == Contain::IN) {
//             std::cout << "1\n";
//         } else if (res == Contain::OUT) {
//             std::cout << "0\n";
//         } else {
//             assert(0);
//         }
//     }
//     return 0;
// }
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0412"

#include <iostream>

#include <type_traits>

// Constants (EPS, PI)
// EPS の変更は Constants<T>::set_eps(new_eps) で
template <class T> struct Constants {
    static T EPS;
    static void set_eps(const T e) { EPS = e; }
    static constexpr T PI = 3.14159'26535'89793L;
};

template <> double Constants<double>::EPS = 1e-9;
template <> long double Constants<long double>::EPS = 1e-12;
template <> long long Constants<long long>::EPS = 0;

// 汎用関数
template <class T> inline int sign(const T x) { return x < -Constants<T>::EPS ? -1 : (x > Constants<T>::EPS ? 1 : 0); }
template <class T> inline bool equal(const T a, const T b) { return sign(a - b) == 0; }
template <class T> inline T radian_to_degree(const T r) { return r * 180.0 / Constants<T>::PI; }
template <class T> inline T degree_to_radian(const T d) { return d * Constants<T>::PI / 180.0; }

// type traits
template <class T> using is_geometry_floating_point = typename std::conditional<std::is_same<T, double>::value || std::is_same<T, long double>::value, std::true_type, std::false_type>::type;
template <class T> using is_geometry_integer = typename std::conditional<std::is_same<T, long long>::value, std::true_type, std::false_type>::type;
template <class T> using is_geometry = typename std::conditional<is_geometry_floating_point<T>::value || is_geometry_integer<T>::value, std::true_type, std::false_type>::type;

#include <cmath>
#include <cassert>

// 点
template <class T> struct Point {
    T x, y;

    Point() = default;
    Point(const T x, const T y) : x(x), y(y) {}

    Point& operator+=(const Point& p) {
        x += p.x, y += p.y;
        return *this;
    }
    Point& operator-=(const Point& p) {
        x -= p.x, y -= p.y;
        return *this;
    }
    Point& operator*=(const Point& p) {
        static_assert(is_geometry_floating_point<T>::value == true);
        return *this = Point(x * p.x - y * p.y, x * p.y + y * p.x);
    }
    Point& operator/=(const Point& p) {
        static_assert(is_geometry_floating_point<T>::value == true);
        return *this = Point(x * p.x + y * p.y, -x * p.y + y * p.x) / (p.x * p.x + p.y * p.y);
    }
    Point& operator*=(const T k) {
        x *= k, y *= k;
        return *this;
    }
    Point& operator/=(const T k) {
        static_assert(is_geometry_floating_point<T>::value == true);
        x /= k, y /= k;
        return *this;
    }

    Point operator+() const { return *this; }
    Point operator-() const { return Point(-x, -y); }

    friend Point operator+(const Point& a, const Point& b) { return Point(a) += b; }
    friend Point operator-(const Point& a, const Point& b) { return Point(a) -= b; }
    friend Point operator*(const Point& a, const Point& b) { return Point(a) *= b; }
    friend Point operator/(const Point& a, const Point& b) { return Point(a) /= b; }
    friend Point operator*(const Point& p, const T k) { return Point(p) *= k; }
    friend Point operator/(const Point& p, const T k) { return Point(p) /= k; }

    // 辞書式順序
    friend bool operator<(const Point& a, const Point& b) { return a.x == b.x ? a.y < b.y : a.x < b.x; }
    friend bool operator>(const Point& a, const Point& b) { return a.x == b.x ? a.y > b.y : a.x > b.x; }
    friend bool operator==(const Point& a, const Point& b) { return a.x == b.x and a.y == b.y; }

    // I/O
    friend std::istream& operator>>(std::istream& is, Point& p) { return is >> p.x >> p.y; }
    friend std::ostream& operator<<(std::ostream& os, const Point& p) { return os << '(' << p.x << ' ' << p.y << ')'; }
};

// 汎用関数
// 点の一致判定
template <class T> inline bool equal(const Point<T>& a, const Point<T>& b) { return equal(a.x, b.x) and equal(a.y, b.y); }
// 内積
template <class T> inline T dot(const Point<T>& a, const Point<T>& b) { return a.x * b.x + a.y * b.y; }
// 外積
template <class T> inline T cross(const Point<T>& a, const Point<T>& b) { return a.x * b.y - a.y * b.x; }
// rad ラジアンだけ反時計回りに回転
template <class T> inline Point<T> rotate(const Point<T>& p, const T theta) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return p * Point<T>(std::cos(theta), std::sin(theta));
}
// (x, y) の辞書式順序 (誤差許容)
template <class T> inline bool compare_x(const Point<T>& a, const Point<T>& b) { return equal(a.x, b.x) ? sign(a.y - b.y) < 0 : sign(a.x - b.x) < 0; }
// (y, x) の辞書式順序 (誤差許容)
template <class T> inline bool compare_y(const Point<T>& a, const Point<T>& b) { return equal(a.y, b.y) ? sign(a.x - b.x) < 0 : sign(a.y - b.y) < 0; }
// 整数のまま行う偏角ソート
// 無限の精度をもつ arg(p) = atan2(y, x) で比較し, 同じ場合は norm(p) で比較 (atan2(0, 0) = 0 とする)
// 基本的に (-PI, PI] でソートされ, 点 (0, 0) は (-PI, 0) と [0, PI] の間に入る
// https://ngtkana.hatenablog.com/entry/2021/11/13/202103
// https://judge.yosupo.jp/problem/sort_points_by_argument
template <class T> inline bool compare_atan2(const Point<T>& a, const Point<T>& b) {
    static_assert(is_geometry_integer<T>::value == true);
    if ((Point<T>(a.y, -a.x) > Point<T>(0, 0)) == (Point<T>(b.y, -b.x) > Point<T>(0, 0))) {  // a, b in (-PI, 0] or a, b in (0, PI]
        if (a.x * b.y != a.y * b.x) return a.x * b.y > a.y * b.x;                            // cross(a, b) != 0
        return a == Point<T>(0, 0) ? b.x > 0 and b.y == 0 : (b == Point<T>(0, 0) ? a.y < 0 : norm(a) < norm(b));
    }
    return Point<T>(a.y, -a.x) < Point<T>(b.y, -b.x);
}
// 絶対値の 2 乗
template <class T> inline T norm(const Point<T>& p) { return p.x * p.x + p.y * p.y; }
// 絶対値
template <class T> inline T abs(const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return std::sqrt(norm(p));
}
// 偏角
template <class T> inline T arg(const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return std::atan2(p.y, p.x);  // (-PI, PI]
}
// 共役複素数 (x 軸について対象な点)
template <class T> inline Point<T> conj(const Point<T>& p) { return Point(p.x, -p.y); }
// 極座標系 -> 直交座標系 (絶対値が rho で偏角が theta ラジアン)
template <class T> inline Point<T> polar(const T rho, const T theta = T(0)) {
    static_assert(is_geometry_floating_point<T>::value == true);
    assert(sign(rho) >= 0);
    return Point<T>(std::cos(theta), std::sin(theta)) * rho;
}
// ccw の戻り値
enum class Ccw {
    COUNTER_CLOCKWISE = 1,  // a->b->c 反時計回り
    CLOCKWISE = -1,         // a->b->c 時計回り
    ONLINE_BACK = 2,        // c->a->b 直線
    ONLINE_FRONT = -2,      // a->b->c 直線
    ON_SEGMENT = 0          // a->c->b 直線
};
// 点 a, b, c の位置関係
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
template <class T> Ccw ccw(const Point<T>& a, const Point<T>& b, const Point<T>& c) {
    Point<T> ab = b - a;
    Point<T> ac = c - a;
    if (sign(cross(ab, ac)) == 1) return Ccw::COUNTER_CLOCKWISE;
    if (sign(cross(ab, ac)) == -1) return Ccw::CLOCKWISE;
    if (sign(dot(ab, ac)) == -1) return Ccw::ONLINE_BACK;
    if (sign(norm(ab) - norm(ac)) == -1) return Ccw::ONLINE_FRONT;
    return Ccw::ON_SEGMENT;
}
// 線分 a -> b から 線分 a -> c までの角度 (ラジアンで -PI より大きく PI 以下)
template <class T> T get_angle(const Point<T>& a, const Point<T>& b, const Point<T>& c) {
    Point<T> ab = b - a;
    Point<T> ac = c - a;
    // a-bが x 軸になるように回転
    ac *= conj(ab) / norm(ab);
    return arg(ac);  // (-PI, PI]
}

#include <vector>

// 多角形
template <class T> using Polygon = std::vector<Point<T>>;
template <class T> std::istream& operator>>(std::istream& is, Polygon<T>& p) {
    for (auto&& pi : p) is >> pi;
    return is;
}
template <class T> std::ostream& operator<<(std::ostream& os, const Polygon<T>& p) {
    for (auto&& pi : p) os << pi << " -> ";
    return os;
}

// 多角形の面積 (符号付き)
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
// return area * 2
template <class T> T area2(const Polygon<T>& p) {
    const int n = (int)(p.size());
    assert(n >= 2);
    T res = T(0);
    for (int i = 0; i < n; i++) res += cross(p[i], p[i + 1 == n ? 0 : i + 1]);
    // counter clockwise: res > 0
    // clockwise: res < 0
    return res;
}
template <class T> T area(const Polygon<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return area2(p) / T(2);
}

// 多角形の凸判定 (角度が 0 でも PI でも許容)
// 許容したくないときには ON_SEGMENT, ONLINE_FRONT, ONLINE_BACK が出てきたら false を返せば OK
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
template <class T> bool is_convex(const Polygon<T>& p) {
    const int n = (int)(p.size());
    assert(n >= 3);
    bool okccw = true, okcw = true;
    for (int i = 0; i < n; i++) {
        auto res = ccw(p[i], p[i + 1 >= n ? i + 1 - n : i + 1], p[i + 2 >= n ? i + 2 - n : i + 2]);
        if (res == Ccw::CLOCKWISE) okccw = false;
        if (res == Ccw::COUNTER_CLOCKWISE) okcw = false;
        if (!okccw and !okcw) return false;
    }
    return true;
}

#include <algorithm>

// 凸包 (Andrew's Monotone Chain algorithm)
// O(n log n)
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
// (x, y) を辞書式順序でソートし, スタックを使って上側凸包と下側凸包を求める
// 反時計回り
// strict を true にすると凸包の辺上に並ぶ頂点は含めない (頂点数が最小になる)
template <class T> Polygon<T> convex_hull_monotone_chain(std::vector<Point<T>>& p, bool strict = true) {
    if (is_geometry_integer<T>::value) {
        std::sort(p.begin(), p.end());
    } else {
        assert(is_geometry_floating_point<T>::value);
        std::sort(p.begin(), p.end(), compare_x<T>);
    }
    p.erase(std::unique(p.begin(), p.end()), p.end());
    const int n = (int)(p.size());
    if (n <= 2) return p;
    Polygon<T> r;
    r.reserve(n * 2);
    auto f = [&strict](Ccw ccwres) -> bool { return strict ? ccwres != Ccw::CLOCKWISE : ccwres == Ccw::COUNTER_CLOCKWISE; };
    for (int i = 0; i < n; i++) {
        while (r.size() >= 2 and f(ccw(r[r.size() - 2], r[r.size() - 1], p[i]))) {
            r.pop_back();
        }
        r.push_back(p[i]);
    }
    int t = r.size() + 1;
    for (int i = n - 2; i >= 0; i--) {
        while (r.size() >= t and f(ccw(r[r.size() - 2], r[r.size() - 1], p[i]))) {
            r.pop_back();
        }
        r.push_back(p[i]);
    }
    r.pop_back();
    std::reverse(r.begin(), r.end());
    return r;
}

// 直線
template <class T> struct Line {
    Point<T> a, b;

    Line() = default;
    Line(const Point<T>& a, const Point<T>& b) : a(a), b(b) {}

    // Ax + By = C
    Line(const T A, const T B, const T C) {
        static_assert(is_geometry_floating_point<T>::value == true);
        assert(!(equal(A, T(0)) and equal(B, T(0))));
        if (equal(A, T(0))) {
            a = Point<T>(T(0), C / B), b = Point<T>(T(1), C / B);
        } else if (equal(B, T(0))) {
            a = Point<T>(C / A, T(0)), b = Point<T>(C / A, T(1));
        } else if (equal(C, T(0))) {
            a = Point<T>(T(0), T(0)), b = Point<T>(T(1), -A / B);
        } else {
            a = Point<T>(T(0), C / B), b = Point<T>(C / A, T(0));
        }
    }

    friend std::istream& operator>>(std::istream& is, Line& p) { return is >> p.a >> p.b; }
    friend std::ostream& operator<<(std::ostream& os, const Line& p) { return os << p.a << "->" << p.b; }
};

// 線分
template <class T> struct Segment : Line<T> {
    Segment() = default;

    Segment(const Point<T>& a, const Point<T>& b) : Line<T>(a, b) {}
};

// 点 p から直線 l に下ろした垂線と直線 l の交点
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
template <class T> Point<T> projection(const Line<T>& l, const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    T t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return l.a + (l.b - l.a) * t;
}

// 直線 l に関して点 p と対象な位置にある点
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
template <class T> Point<T> reflection(const Line<T>& l, const Point<T>& p) {
    static_assert(is_geometry_floating_point<T>::value == true);
    return p + (projection(l, p) - p) * T(2);
}

// 直線 l1, l2 の垂直判定
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
template <class T> inline bool is_orthogonal(const Line<T>& l1, const Line<T>& l2) { return sign(dot(l1.b - l1.a, l2.b - l2.a)) == 0; }

// 直線 l1, l2 の平行判定
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
template <class T> inline bool is_parallel(const Line<T>& l1, const Line<T>& l2) { return sign(cross(l1.b - l1.a, l2.b - l2.a)) == 0; }

// 円
template <class T> struct Circle {
    Point<T> o;
    T r;

    Circle() = default;
    Circle(const Point<T>& o, const T r) : o(o), r(r) {}

    friend std::istream& operator>>(std::istream& is, Circle& c) { return is >> c.o >> c.r; }
    friend std::ostream& operator<<(std::ostream& os, const Circle& c) { return os << c.o << ", " << c.r; }
};

// 共通接線の本数
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A
template <class T> int tangent_number(Circle<T> c1, Circle<T> c2) {
    if (c1.r < c2.r) std::swap(c1, c2);
    const T d2 = norm(c1.o - c2.o);
    if (sign(d2 - (c1.r + c2.r) * (c1.r + c2.r)) == 1) return 4;  // d > c1.r + c2.r and c1.r + c2.r >= 0 <=> d ^ 2 > (c1.r + c2.r) ^ 2
    if (sign(d2 - (c1.r + c2.r) * (c1.r + c2.r)) == 0) return 3;  // d = c1.r + c2.r and c1.r + c2.r >= 0 <=> d ^ 2 = (c1.r + c2.r) ^ 2
    if (sign(d2 - (c1.r - c2.r) * (c1.r - c2.r)) == 1) return 2;  // d > c1.r - c2.r and c1.r - c2.r >= 0 <=> d ^ 2 > (c1.r - c2.r) ^ 2
    if (sign(d2 - (c1.r - c2.r) * (c1.r - c2.r)) == 0) return 1;  // d = c1.r - c2.r and c1.r - c2.r >= 0 <=> d ^ 2 = (c1.r - c2.r) ^ 2
    return 0;
}

// 交差判定 (直線, 線分, 円, 点)
// 直線 l1, l2 の交差判定
template <class T> bool is_intersect(const Line<T>& l1, const Line<T>& l2) {
    Point<T> base = l1.b - l1.a;
    T d12 = cross(base, l2.b - l2.a);
    T d1 = cross(base, l1.b - l2.a);
    // sign(d12) != 0 -> 平行でないので交差する
    // sign(d12) == 0 and sign(d1) == 0 -> 一致するので交差する
    return sign(d12) != 0 or sign(d1) == 0;
}
// 直線 l, 点 p の交差判定
template <class T> inline bool is_intersect(const Line<T>& l, const Point<T>& p) {
    auto res = ccw(l.a, l.b, p);
    return res == Ccw::ONLINE_BACK or res == Ccw::ONLINE_FRONT or res == Ccw::ON_SEGMENT;
}
template <class T> bool is_intersect(const Point<T>& p, const Line<T>& l) { return is_intersect(l, p); }

// 線分 s, 点 p の交差判定
template <class T> inline bool is_intersect(const Segment<T>& s, const Point<T>& p) { return ccw(s.a, s.b, p) == Ccw::ON_SEGMENT; }
template <class T> inline bool is_intersect(const Point<T>& p, const Segment<T>& s) { return ccw(s.a, s.b, p) == Ccw::ON_SEGMENT; }

// 直線 l, 線分 s の交差判定
template <class T> bool is_intersect(const Line<T>& l, const Segment<T>& s) {
    // s.a と s.b が直線 l に関して同じ側 (直線上を除き) にある場合に限り交差しない
    auto c1 = ccw(l.a, l.b, s.a);
    auto c2 = ccw(l.a, l.b, s.b);
    return !((c1 == c2) and (c1 == Ccw::CLOCKWISE or c1 == Ccw::COUNTER_CLOCKWISE));
}
template <class T> bool is_intersect(const Segment<T>& s, const Line<T>& l) { return is_intersect(l, s); }

// 線分 s1, s2 の交差判定
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
template <class T> inline bool is_intersect(const Segment<T>& s1, const Segment<T>& s2) {
    auto c1 = ccw(s1.a, s1.b, s2.a);
    auto c2 = ccw(s1.a, s1.b, s2.b);
    auto c3 = ccw(s2.a, s2.b, s1.a);
    auto c4 = ccw(s2.a, s2.b, s1.b);
    // 平行な場合: 重なるなら 1 次元で考えると必ず端点のどれかがもう一方の線分上にある
    if (c1 == Ccw::ON_SEGMENT or c2 == Ccw::ON_SEGMENT or c3 == Ccw::ON_SEGMENT or c4 == Ccw::ON_SEGMENT) return true;
    // 平行でない場合: 一方の線分の両側にもう一方の線分の端点がある, を線分を入れ替えても成立
    // 平行だが重ならない場合は以下の条件は成立しない
    bool ok1 = ((c1 == Ccw::CLOCKWISE and c2 == Ccw::COUNTER_CLOCKWISE) or (c1 == Ccw::COUNTER_CLOCKWISE and c2 == Ccw::CLOCKWISE));
    bool ok2 = ((c3 == Ccw::CLOCKWISE and c4 == Ccw::COUNTER_CLOCKWISE) or (c3 == Ccw::COUNTER_CLOCKWISE and c4 == Ccw::CLOCKWISE));
    return ok1 and ok2;
}

// 点 p1, p2 の交差判定
template <class T> inline bool is_intersect(const Point<T>& p1, const Point<T>& p2) { return equal(p1, p2); }

// 円 c1, c2 の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c1, const Circle<T>& c2) {
    const int num = tangent_number(c1, c2);
    return 1 <= num and num <= 3;
}

// 円 c, 点 p の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c, const Point<T>& p) { return equal(norm(p - c.o), c.r * c.r); }
template <class T> inline bool is_intersect(const Point<T>& p, const Circle<T>& c) { return equal(norm(p - c.o), c.r * c.r); }

// 円 c, 直線 l の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c, const Line<T>& l) {
    static_assert(is_geometry_floating_point<T>::value == true);
    // norm(c.o - projection(l, c.o)) が直線 l と 円 c の中心 c.o の距離の 2 乗
    return sign(c.r * c.r - norm(c.o - projection(l, c.o))) >= 0;
}
template <class T> inline bool is_intersect(const Line<T>& l, const Circle<T>& c) { return is_intersect(c, l); }

// 円 c, 線分 s の交差判定
template <class T> inline bool is_intersect(const Circle<T>& c, const Segment<T>& s) {
    static_assert(is_geometry_floating_point<T>::value == true);
    if (!is_intersect(c, Line(s.a, s.b))) return false;  // 直線としても交差しない
    T d1 = abs(c.o - s.a), d2 = abs(c.o - s.b);
    if (sign(d1 - c.r) == -1 and sign(d2 - c.r) == -1) return false;  // 端点がどちらも円の内側
    if (sign(d1 - c.r) * sign(d2 - c.r) <= 0) return true;            // 円周をまたいでいる
    const Point<T> h = projection(s, c.o);
    return ccw(s.a, s.b, h) == Ccw::ON_SEGMENT;  // s.a -> h -> s.b の順で並んでいる
}
template <class T> inline bool is_intersect(const Segment<T>& s, const Circle<T>& c) { return is_intersect(c, s); }

enum class Contain { IN, ON, OUT };

// 円 c と点 p の位置関係
template <class T> Contain contain(const Circle<T>& c, const Point<T>& p) {
    int sgn = sign(norm(p - c.o) - c.r * c.r);
    return sgn == 1 ? Contain::OUT : (sgn == 0 ? Contain::ON : Contain::IN);
}

// 多角形 (凸とは限らない) q と点 p の位置関係
// 頂点は反時計回りに並んでいる
// O(n)
// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
template <class T> Contain contain(const Polygon<T>& q, const Point<T>& p) {
    const int n = (int)(q.size());
    assert(n >= 3);
    bool x = false;
    for (int i = 0; i < n; i++) {
        if (is_intersect(Segment(q[i], q[(i + 1) % n]), p)) return Contain::ON;
        Point a = q[i] - p, b = q[(i + 1) % n] - p;
        if (a.y > b.y) std::swap(a, b);
        // a.y < b.y
        // check each point's y is 0 at most 1 times
        if (sign(a.y) <= 0 and sign(b.y) > 0 and sign(cross(a, b)) > 0) x = !x;
    }
    return (x ? Contain::IN : Contain::OUT);
}

// 凸多角形 (すべての内角が 180° 未満) q と点 p の位置関係
// 頂点は反時計回りに並んでいる
// O(log n)
// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0412
// https://atcoder.jp/contests/abc296/tasks/abc296_g
template <class T> Contain convex_contain(const Polygon<T>& q, const Point<T>& p) {
    const int n = (int)(q.size());
    assert(n >= 3);
    auto c1 = ccw(q[0], q[1], p);
    auto c2 = ccw(q[0], q[n - 1], p);
    if (c1 == Ccw::CLOCKWISE or c2 == Ccw::COUNTER_CLOCKWISE) return Contain::OUT;
    if (c1 == Ccw::ON_SEGMENT or c2 == Ccw::ON_SEGMENT) return Contain::ON;
    if (c1 == Ccw::ONLINE_FRONT or c2 == Ccw::ONLINE_FRONT) return Contain::OUT;
    // 二分探索 (q[0] -> q[i] -> p が反時計回りになるような最大の i)
    int ok = 1, ng = n - 1;
    while (ng - ok > 1) {
        int md = (ok + ng) / 2;
        if (ccw(q[0], q[md], p) == Ccw::COUNTER_CLOCKWISE) {
            ok = md;
        } else {
            ng = md;
        }
    }
    // 直線 q[ok] -> q[ok + 1] を基準に考える
    auto c3 = ccw(q[ok], q[ok + 1], p);
    assert(c3 != Ccw::ONLINE_FRONT);
    assert(c3 != Ccw::ONLINE_BACK);
    return c3 == Ccw::ON_SEGMENT ? Contain::ON : (c3 == Ccw::COUNTER_CLOCKWISE ? Contain::IN : Contain::OUT);
}

int main() {
    int N;
    std::cin >> N;
    Polygon<long double> q(N);
    std::cin >> q;
    q = convex_hull_monotone_chain(q, true);
    for (int i = 0; i < N; i++) q[i] *= 1e6 / (1e6 - 1e2);
    int Q;
    std::cin >> Q;
    for (int i = 0; i < Q; i++) {
        Point<long double> p;
        std::cin >> p;
        auto res = convex_contain(q, p);
        if (res == Contain::IN) {
            std::cout << "1\n";
        } else if (res == Contain::OUT) {
            std::cout << "0\n";
        } else {
            assert(0);
        }
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 5024
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<long double>x,y;
bool Judge(long double e1,long double e2,long double e3,long double e4,long double r1,long double r2,long double r3,long double r4){
    long double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    long double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        x[i]+=(x[i])/9999;
        y[i]+=(y[i])/9999;
        //x[i]=-1000000*(x[i]/-999900);
        //y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.21052631578947367
time_ms: 50
memory_kb: 3432
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<long double>x,y;
bool Judge(long double e1,long double e2,long double e3,long double e4,long double r1,long double r2,long double r3,long double r4){
    long double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    long double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        x[i]+=(x[i])/1999;
        y[i]+=(y[i])/1999;
        //x[i]=-1000000*(x[i]/-999900);
        //y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.15789473684210525
time_ms: 50
memory_kb: 3424
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<long double>x,y;
bool Judge(long double e1,long double e2,long double e3,long double e4,long double r1,long double r2,long double r3,long double r4){
    long double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    long double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        //x[i]+=(x[i])/9999;
        //y[i]+=(y[i])/9999;
        x[i]=-1000000*(x[i]/-999900);
        y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.21052631578947367
time_ms: 40
memory_kb: 3512
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<long double>x,y;
bool Judge(long double e1,long double e2,long double e3,long double e4,long double r1,long double r2,long double r3,long double r4){
    long double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0||s==0&&t==0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0||s==0&&t==0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    long double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        x[i]+=(x[i])/9999;
        y[i]+=(y[i])/9999;
        //x[i]=-1000000*(x[i]/-999900);
        //y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.21052631578947367
time_ms: 50
memory_kb: 3516
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<double>x,y;
bool Judge(double e1,double e2,double e3,double e4,double r1,double r2,double r3,double r4){
    double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0||s==0&&t==0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0||s==0&&t==0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        x[i]+=(x[i])/9999;
        y[i]+=(y[i])/9999;
        //x[i]=-1000000*(x[i]/-999900);
        //y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.21052631578947367
time_ms: 40
memory_kb: 3500
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<double>x,y;
int Judge(double e1,double e2,double e3,double e4,double r1,double r2,double r3,double r4){
    double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        x[i]+=(x[i])/9999;
        y[i]+=(y[i])/9999;
        //x[i]=-1000000*(x[i]/-999900);
        //y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.21052631578947367
time_ms: 40
memory_kb: 3500
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
int n;
vector<double>x,y;
int Judge(double e1,double e2,double e3,double e4,double r1,double r2,double r3,double r4){
    double s,t;
    s=(e1-e2)*(r3-r1)-(r1-r2)*(e3-e1);
    t=(e1-e2)*(r4-r1)-(r1-r2)*(e4-e1);
    if(s*t>0){
        return false;
    }
    s=(e3-e4)*(r1-r3)-(r3-r4)*(e1-e3);
    t=(e3-e4)*(r2-r3)-(r3-r4)*(e2-e3);
    if(s*t>0){
        return false;
    }
    return true;
}
bool ftan(int a,int b){
    double g1,g2,h1,h2,p1,p2,p3,p4,p5,p6;
    g1=x[n-1]-x[0];
    g2=y[n-1]-y[0];
    h1=x[1]-x[0];
    h2=y[1]-y[0];
    p1=a-x[0];
    p2=b-y[0];
    p3=p1-h1;
    p4=p2-h2;
    p5=p1-g1;
    p6=p2-g2;
    if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
        //二部探索------------------------------------
        int wl=1,wr=n-1,wm=(wl+wr)/2;
        while(wr-wl>1){
            wm=(wl+wr)/2;
            g1=x[wm]-x[0];
            g2=y[wm]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
                wr=wm;
            }else{
                wl=wm;
            }
        }
            g1=x[wr]-x[0];
            g2=y[wr]-y[0];
            h1=x[wl]-x[0];
            h2=y[wl]-y[0];
            p3=p1-h1;
            p4=p2-h2;
            p5=p1-g1;
            p6=p2-g2;
        if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(h1,0,p1,p5,h2,0,p2,p6)){
            p3=p1+g1-h1;
            p4=p2+g2-h2;
            p5=p1+g1;
            p6=p2+g2;
            if(Judge(g1,0,p1,p3,g2,0,p2,p4)&&Judge(g1,h1,p1,p5,g2,h2,p2,p6)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }

    }else{
        return false;
    }

}
int main(){
    cin>>n;
    x.resize(n);
    y.resize(n);
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        //x[i]+=(x[i])/9999;
        //y[i]+=(y[i])/9999;
        x[i]=-1000000*(x[i]/-999900);
        y[i]=-1000000*(y[i]/-999900);
    }
    int q;cin>>q;
    for(int qwe=0;qwe<q;qwe++){
        int s1,t1;cin>>s1>>t1;
        bool u=ftan(s1,t1);
        if(u){
            cout<<"1\n";
        }else{
            cout<<"0\n";
        }
    }
}
accuracy: 0.21052631578947367
time_ms: 50
memory_kb: 3500
final_rank: 17