题意:问有多少个黑点在任意三个红点组成的三角形内
题解:必然一眼能看出是求点在红色点组成的凸包内吧。然后暴力枚举黑点与凸包判叉积的话会T,所以有一个优化是,将凸包分成x个三角形(固定一个起点,枚举任意两个相邻的点),然后进行二分,找到一个叉积>=0 一个<=0的时候,再判断是否在第三条边左侧就ok了(因为在凸包外也有满足叉积>=0 && 叉积<=0的情况)
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <map>
#include <sstream>
#define LL long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-8
const int maxn = 200000 + 5;
using namespace std;
struct Point
{
double x;
double y;
Point(){}
Point(double xx, double yy):x(xx),y(yy){}
}p[maxn],pt[maxn];
vector<Point> vec;
//小于0表示p2在p0p1右侧
double cross(Point p0, Point p1, Point p2)
{
return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
}
//计算距离
double dis(Point p1, Point p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
bool cmp(const Point &p1, const Point &p2)
{
double temp = cross(p[0], p1, p2);
if (fabs(temp) < 1e-6)//极角相等按照距离从小到大排序
{
return dis(p[0], p1) < dis(p[0], p2);
}
else
{
return temp > 0;
}
}
vector<Point> graham_scan(int n)
{
vector<Point> ch;
int top = 2;
int index = 0;
for (int i = 1; i < n; ++i)//选出Y坐标最小的点,若Y坐标相等,选择X坐标小的点
{
if (p[i].y < p[index].y || (p[i].y == p[index].y && p[i].x < p[index].x))
{
index = i;
}
}
swap(p[0], p[index]);
ch.push_back(p[0]);
//按极角排序
sort(p + 1, p + n, cmp);
ch.push_back(p[1]);
ch.push_back(p[2]);
for (int i = 3; i < n; ++i)
{
while (top > 0 && cross(ch[top - 1], p[i], ch[top]) >= 0)
{
--top;
ch.pop_back();
}
ch.push_back(p[i]);
++top;
}
return ch;
}
bool solve(Point pp, vector<Point> vec){
int size = (int)vec.size();
Point p0 = vec[0];
int l = 1, r = size-2;
while(l <= r){
int m = (l+r)/2;
double flag1 = cross(p0,vec[m],pp);
double flag2 = cross(p0,vec[m+1],pp);
//flag1 < 0 表示 pp 在 p0 vec[m+1] 右侧
if(flag1 >= 0 && flag2 <= 0){
double flag3 = cross(vec[m],vec[m+1],pp);
if(flag3 >= 0)
return true;
return false;
}
if(flag1 < 0){
r = m - 1;
}
else{
l = m + 1;
}
}
return false;
}
int main(){
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
vec = graham_scan(n);
int m;
scanf("%d",&m);
for(int i=0; i<m; i++)
scanf("%lf%lf",&pt[i].x,&pt[i].y);
int ans = 0;
for(int i=0; i<m; i++){
if(solve(pt[i], vec)){
ans++;
}
}
printf("%d\n",ans);
}
/*
8
3 4
2 8
5 4
1 8
4 7
3 10
11 2
7 3
6
5 12
3 7
3 3
4 5
0 4
2 6
*/