#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
// Struktura reprezentująca punkt/wektor
struct Point {
long long x, y;
};
// Iloczyn wektorowy (cross product) wektorów OA i OB
// Zwraca wartość dodatnią, ujemną lub 0
long long cross_product(const Point& O, const Point& A, const Point& B) {
return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}
// Funkcja sprawdzająca, czy punkt P znajduje się wewnątrz wielokąta wypukłego
bool is_inside_polygon(const Point& P, const vector<Point>& poly) {
int n = poly.size();
// Sprawdzamy orientację względem pierwszego i ostatniego boku
if (cross_product(poly[0], poly[1], P) < 0) return false;
if (cross_product(poly[0], poly[n - 1], P) > 0) return false;
// Wyszukiwanie binarne odpowiedniego segmentu kątowego
int low = 1, high = n - 1;
while (high - low > 1) {
int mid = (low + high) / 2;
if (cross_product(poly[0], poly[mid], P) >= 0) {
low = mid;
} else {
high = mid;
}
}
return cross_product(poly[low], poly[high], P) >= 0;
}
// Komparator do sortowania kątowego wokół punktu P
struct AngularCompare {
Point P;
AngularCompare(Point p) : P(p) {}
// Funkcja pomocnicza określająca półpłaszczyznę (góra/dół)
int half_plane(const Point& q) const {
if (q.y == P.y) {
return q.x < P.x ? 1 : 0;
}
return q.y < P.y ? 1 : 0;
}
bool operator()(const Point& a, const Point& b) const {
int hp_a = half_plane(a);
int hp_b = half_plane(b);
if (hp_a != hp_b) {
return hp_a < hp_b;
}
long long cp = (a.x - P.x) * (b.y - P.y) - (a.y - P.y) * (b.x - P.x);
return cp > 0; // Sortowanie przeciwnie do ruchu wskazówek zegara
}
};
long long solve_for_point(int n, const vector<Point>& poly, const Point& P) {
// Jeśli punkt jest poza wielokątem, nie może być w żadnym trójkącie
if (!is_inside_polygon(P, poly)) {
return 0;
}
// Tworzymy listę wierzchołków posortowaną kątowo względem P
vector<Point> pts = poly;
sort(pts.begin(), pts.end(), AngularCompare(P));
// Dublujemy tablicę, aby łatwo symulować cykliczność (gąsienica)
for (int i = 0; i < n; i++) {
pts.push_back(pts[i]);
}
long long bad_triangles = 0;
int j = 0;
// Metoda dwóch wskaźników
for (int i = 0; i < n; i++) {
if (j <= i) j = i + 1;
// Rozszerzamy okno gąsienicy tak długo, jak punkty leżą po jednej stronie prostej
while (j < i + n && cross_product(P, pts[i], pts[j]) > 0) {
j++;
}
long long count = j - i - 1;
if (count >= 2) {
// Kombinacja symbolu Newtona: count po 2
bad_triangles += (count * (count - 1)) / 2;
}
}
// Łączna liczba wszystkich trójkątów: n po 3
long long total_triangles = (1LL * n * (n - 1) * (n - 2)) / 6;
return total_triangles - bad_triangles;
}
int main() {
// Optymalizacja wejścia/wyjścia
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
if (!(cin >> n)) return 0;
vector<Point> poly(n);
for (int i = 0; i < n; i++) {
cin >> poly[i].x >> poly[i].y;
}
// Upewniamy się, że wielokąt jest zorientowany przeciwnie do wskazówek zegara (CCW)
// Jeśli wejście jest CW (zgodnie z treścią zadania), odwracamy wektor
long long area = 0;
for (int i = 0; i < n; i++) {
int next = (i + 1) % n;
area += (poly[i].x * poly[next].y - poly[next].x * poly[i].y);
}
if (area < 0) {
reverse(poly.begin(), poly.end());
}
int t;
if (cin >> t) {
while (t--) {
Point P;
cin >> P.x >> P.y;
cout << solve_for_point(n, poly, P) << "\n";
}
}
return 0;
}