题目
按逆时针顺序给出三个凸包点集 (mathbb{A,B,C}),每次查询给出点 (D),
问是否存在点 (Ainmathbb{A},Binmathbb{B},Cinmathbb{C}) 满足 (D) 为 (Delta{ABC}) 的重心。
分析
考虑重心的坐标就是 ((frac{x_1+x_2+x_3}{3},frac{y_1+y_2+y_3}{3}))
那么如果将 (D) 的坐标扩大三倍,那么也就是问 (mathbb{A,B,C}) 三个凸包按照坐标分别相加组装成一个新的凸包,点 (D) 是否在这个凸包中。
可以发现三个凸包可以直接利用闵可夫斯基和合并起来,然后判断点是否位于多边形内部即可
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=150011;
typedef long long lll; int n,m,_n;
struct Point{
lll x,y;
inline Point operator -(const Point &t)const{
return (Point){x-t.x,y-t.y};
}
inline Point operator +(const Point &t)const{
return (Point){x+t.x,y+t.y};
}
}a[3][N],_a[N],b[N],B,seg[2][N];
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline lll Dis(Point x){return x.x*x.x+x.y*x.y;}
inline lll cj(Point x,Point y){return x.x*y.y-x.y*y.x;}
inline lll dj(Point x,Point y){return x.x*y.x+x.y*y.y;}
bool cmp(Point x,Point y){
rr lll t=cj(x-B,y-B);
return t>0||(!t&&Dis(x-B)<Dis(y-B));
}
inline bool within(Point p){
rr Point _p=p-a[2][1];
if (cj(_p,_a[2])>0||cj(_p,_a[_n])<0) return 0;
rr int l=2,r=_n-1;
while (l<=r){
rr int mid=(l+r)>>1;
if (cj(_p,_a[mid])<=0&&cj(_p,_a[mid+1])>=0)
return cj(_a[mid+1]-_p,_a[mid]-_p)<=0;
else if (cj(_p,_a[mid])>0) r=mid-1;
else l=mid+1;
}
return 0;
}
inline void Convex(Point *a,int &n){
rr int o=1,Top;
for (rr int i=2;i<=n;++i)
if (a[i].x<a[o].x||(a[i].x==a[o].x&&a[i].y<a[o].y)) o=i;
swap(a[o],a[1]),B=a[1],sort(a+2,a+1+n,cmp);
b[Top=1]=a[1];
for (rr int i=2;i<=n;++i){
while (Top>1&&cj(a[i]-b[Top-1],b[Top]-b[Top-1])>=0) --Top;
b[++Top]=a[i];
}
for (rr int i=1;i<=n;++i) a[i]=a[0]; n=Top;
for (rr int i=1;i<=Top;++i) a[i]=b[i],b[i]=a[0];
}
inline void Minkowski(){
for (rr int i=1;i<n;++i) seg[0][i]=a[0][i+1]-a[0][i]; seg[0][n]=a[0][1]-a[0][n];
for (rr int i=1;i<m;++i) seg[1][i]=a[1][i+1]-a[1][i]; seg[1][m]=a[1][1]-a[1][m];
rr int I=1,J=1;
a[2][_n=1]=a[0][1]+a[1][1];
for (;I<=n&&J<=m;++_n)
if (cj(seg[0][I],seg[1][J])>=0)
a[2][_n+1]=a[2][_n]+seg[0][I++];
else a[2][_n+1]=a[2][_n]+seg[1][J++];
for (;I<=n;++_n) a[2][_n+1]=a[2][_n]+seg[0][I++];
for (;J<=m;++_n) a[2][_n+1]=a[2][_n]+seg[1][J++];
}
signed main(){
n=iut(); for (rr int i=1;i<=n;++i) a[0][i]=(Point){iut(),iut()};
m=iut(); for (rr int i=1;i<=m;++i) a[1][i]=(Point){iut(),iut()};
Convex(a[0],n),Convex(a[1],m),Minkowski(),Convex(a[2],_n),n=_n,m=iut();
for (rr int i=1;i<=n;++i) a[0][i]=a[2][i];
for (rr int i=1;i<=m;++i) a[1][i]=(Point){iut(),iut()};
Convex(a[1],m),Minkowski(),Convex(a[2],_n);
for (rr int i=2;i<=_n;++i) _a[i]=a[2][i]-a[2][1];
for (rr int Q=iut();Q;--Q)
puts(within((Point){3*iut(),3*iut()})?"YES":"NO");
return 0;
}