Consider the problem of determining whether a point belongs to a convex polygon.
Suppose the vertices of the polygon are given in counterclockwise order: p_1, p_2, ..., p_n. Fix the vertex p_1. Then all other vertices are ordered around it by polar angle.
Draw rays from point p_1 through the remaining vertices (i.e., the diagonals of the polygon). We can now apply binary search to find an edge p_ip_{i+1} such that the orientations of the triples of points p_1p_iq and p_1p_{i+1}q are different.
Thus, we determine the sector (triangle) in which the point may lie.
After the angle p_ip_1p_{i+1} containing the point is found, we can check in constant time whether the points p_1 and lie on the same side of the line p_ip_{i+1}. For this, the orientation of the triple p_ip_{i+1}q must be left (since the orientation of p_ip_{i+1}p_1 is left, as the polygon vertices are given in counterclockwise order).
At the beginning of the algorithm, it is also necessary to check boundary cases: if the orientation of the triple p_1p_nq is left or the orientation of the triple p_1p_2q is right, then the point lies outside the polygon.
Turn direction. Consider moving from point to point , and then from to point . The turn is considered left (counterclockwise) if the vector (pseudo-scalar) product AB \times BC > 0, and right if AB \times BC < 0.
Algorithm implementation
Let us define a structure and an array of points.
#define MAX 100001
struct Point
{
long long x, y;
Point(long long x = 0, long long y = 0) : x(x), y(y) {}
};
Point p[MAX];The function angle determines whether the turn made when moving through points А, B, С is left or right. To do this, we calculate the corresponding vectors:
The pseudo-scalar (cross) product of AB \times BC is
The sign of this expression determines the direction of the turn:
Positive value — left turn;
Negative value — right turn;
int angle(Point a, Point b, Point c)
{
long long q = (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);
return (q > 0) - (q < 0); // sgn(q)
}The function inside returns if the point lies inside the polygon.
bool inside(Point q)
{We choose the first vertex of the polygon as the base.
Point a = p[1];If the orientation of the triple p_1p_nq is left, or the orientation of the triple p_1p_2q is right, then the point lies outside the angle p_np_1p_2, and therefore outside the polygon.
if (angle(a, p[2], q) < 0 || angle(a, p[n], q) > 0) return false;Perform a binary search on the interval [l; r] = [2; n]. We look for points p_l and p_r~(r = l + 1) such that the point lies inside the angle p_lp_1p_r.
int l = 2, r = n, m;
while (l + 1 < r)
{
m = (l + r) / 2;
if (angle(a, p[m], q) < 0)
r = m;
else
l = m;
}
return angle(p[l], p[r], q) >= 0;
}The main part of the program. Read the input data.
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++)
{
scanf("%lld %lld", &x, &y);
p[i] = Point(x, y);
}Compute the number of points that lie inside the polygon.
res = 0;
for (int i = 1; i <= m; ++i)
{
scanf("%lld %lld", &x, &y);
if (inside(Point(x, y))) res++;
}Print the answer.
if (res < k) puts("NO"); else puts("YES");