題意: 有一個 n 個點組成的凸多邊形, 和 m 個點,問 M 個點是否全部嚴格在多邊形內部。
轉大牛分析:
考慮將一個凸包划分為N個三角區域
於是可知對於某個點,如果不在這些三角區域內,那么必然不在凸包內
否則,可以通過二分位置,得到點所在的區間
之后只需要判斷點 是否在區間所對應的原凸包的邊的左邊即可(逆時針給出凸包點順序)
假設我們查詢綠色的點是否在凸包內,我們首先二分得到了它所在的區間,然后判斷它和綠色的向量的關系,藍色和紫色的點類似,藍色的點在邊界上,紫色的點在邊界右邊
因此一個查詢在O(logN)內解決
code:

#include<stdio.h> #include<string.h> struct node { long long x,y; }a[100005],b[100005]; long long mul(node p1,node p2,node p3) { return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y); } int main() { int n,m,i,low,high,mid,flag; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) scanf("%lld%lld",&a[i].x,&a[i].y); scanf("%d",&m); for(i=0;i<m;i++) scanf("%lld%lld",&b[i].x,&b[i].y); flag=0; for(i=0;i<m;i++) { if(mul(a[0],a[1],b[i])>=0||mul(a[0],a[n-1],b[i])<=0) { flag=1; goto loop; } low=2; high=n-1; while(low<high) { mid=(low+high)>>1; if(mul(a[0],a[mid],b[i])>0) high=mid; else low=mid+1; } if(mul(a[low],a[low-1],b[i])<=0) { flag=1; goto loop; } } loop: if(flag) printf("NO\n"); else printf("YES\n"); } return 0; }