交了快有 20 多发,总是 WA 2 个点。
#include <bits/stdc++.h>
using namespace std;
using LL = __int128;
using Pii = pair<LL, LL>;
const int kMaxN = 2e5 + 5;
int n, m, T, p;
long long tx, ty;
LL ret;
Pii a[kMaxN], b[kMaxN], P = {1e18, 1e18}, Q, X, Y, Z;
Pii make(Pii A, Pii B) { return {B.first - A.first, B.second - A.second}; }
LL operator*(const Pii A, const Pii B) { return A.first * B.second - A.second * B.first; }
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> tx >> ty, a[i].first = tx, a[i].second = ty;
if (P.first > a[i].first || P.first == a[i].first && P.second > a[i].second) {
P = a[i], p = i;
}
}
for (int i = p, j = 1; j <= n; i = i % n + 1, j++) {
b[j] = a[i];
}
b[n + 1] = b[1];
for (int i = 1, j = 2; j <= n + 1; a[++m] = b[i], i = j - 1) {
for (j++; j <= n + 1 && make(b[i], b[j - 1]) * make(b[j - 1], b[j]) == 0; j++) {
}
}
for (P = a[1], cin >> T; T; T--) {
cin >> tx >> ty, Q.first = tx, Q.second = ty;
X = make(P, Q), Y = make(P, a[m]), Z = make(P, a[2]);
if (X * Y == 0 && P.first <= Q.first && Q.first <= a[m].first || X * Z == 0 && P.first <= Q.first && Q.first <= a[2].first) {
cout << "ON\n";
} else if (X * Y <= 0 || X * Z >= 0) {
cout << "OUT\n";
} else {
p = upper_bound(a + 1, a + 1 + m, Q, [](Pii X, Pii Y) { return make(P, X) * make(P, Y) > 0; }) - a - 1;
ret = make(a[p], Q) * make(a[p], a[p + 1]);
if (ret) {
cout << (ret < 0 ? "IN\n" : "OUT\n");
} else {
cout << (a[p].first <= Q.first && Q.first <= a[p + 1].first || a[p + 1].first <= Q.first && Q.first <= a[p].first ? "ON\n" : "OUT\n");
}
}
}
return 0;
}