[JSOI2018]战争
题目描述
九条可怜是一个热爱读书的女孩子。
在她最近正在读的一本小说中,描述了两个敌对部落之间的故事。第一个部落有 nnn 个人,第二个部落有 mmm 个人,每一个人的位置可以抽象成二维平面上坐标为 (xi,yi)(x_i,y_i)(xi,yi) 的点。
在这本书中,人们有很强的领地意识,对于平面上的任何一个点,如果它被三个来自同一部落的人形成的三角形(可能退化成一条线段)包含(包括边界),那么这一个点就属于这一个部落的领地。如果存在一个点同时在两个阵营的领地中,那么这两个部落就会为了争夺这一个点而发生战争。
常年的征战让两个部落不堪重负,因此第二个部落的族长作出了一个英明的决定,他打算选择一个向量 (dx,dy)(dx,dy)(dx,dy) ,让所有的族人都迁徙这个向量的距离,即所有第二阵营的人的坐标都变成 (xi+dx,yi+dy)(x_i+dx,y_i+dy)(xi+dx,yi+dy) 。
现在他计划了 qqq 个迁徙的备选方案,他想要你来帮忙对每一个迁徙方案,计算一下在完成了迁徙之后,两个部落之间还会不会因为争夺领地而发生战争。
输入格式
第一行输入三个整数 n,m,qn,m,qn,m,q,表示两个部落里的人数以及迁徙的备选方案数。
接下来 nnn 行每行两个整数 xi,yix_i,y_ixi,yi 表示第一个部落里的人的坐标。
接下来 mmm 行每行两个整数 xi,yix_i,y_ixi,yi 表示第二个部落里的人的坐标。
接下来 qqq 行每行两个整数 dxi,dyidx_i,dy_idxi,dyi 表示一个迁徙方案。
输入数据保证所有人的坐标两两不同。
输出格式
对于每个迁徙方案,输出一行一个整数,000 表示不会发生冲突,111 表示会发生冲突。
输入输出样例
输入 #1
4 4 3 0 0 1 0 0 1 1 1 -1 0 0 3 0 2 0 -1 0 0 2 3 0 -1
输出 #1
1
0
设a,b为两个部落构成的凸包
b+d=a等价于d=a-b
即取反b,求出凸包,再用Minkowski和合并两凸包
查询用二分查询向量d所在区间,用叉积判断是否在凸包内
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long lol; 7 struct Node 8 { 9 lol x,y; 10 Node operator + (const Node &b) const 11 { 12 return (Node){x+b.x,y+b.y}; 13 } 14 Node operator - (const Node &b) const 15 { 16 return (Node){x-b.x,y-b.y}; 17 } 18 }a[100005],b[100005],sa[200005],sb[200005],sta[200005],bs,s1[200005],s2[200005],s[200005]; 19 int n,m,q,top; 20 bool cmp(Node a,Node b) 21 { 22 if (a.y==b.y) return a.x<b.x; 23 return a.y<b.y; 24 } 25 lol cross(Node a,Node b) 26 { 27 return (a.x*b.y-a.y*b.x); 28 } 29 lol dist(Node a) 30 { 31 return a.x*a.x+a.y*a.y; 32 } 33 bool cmp1(Node A,Node B) 34 { 35 lol t=cross((a[1]-A),(a[1]-B)); 36 if (t==0) return dist(a[1]-A)<dist(a[1]-B); 37 return t>0; 38 } 39 bool cmp2(Node A,Node B) 40 { 41 lol t=cross((b[1]-A),(b[1]-B)); 42 if (t==0) return dist(b[1]-A)<dist(b[1]-B); 43 return t>0; 44 } 45 int grahama(int N) 46 {int i; 47 sort(a+1,a+N+1,cmp); 48 sort(a+2,a+N+1,cmp1); 49 top=0; 50 sa[++top]=a[1]; 51 if (N==1) return 1; 52 sa[++top]=a[2]; 53 for (i=3;i<=N;i++) 54 { 55 while (top>1&&cross(a[i]-sa[top-1],sa[top]-sa[top-1])>=0) top--; 56 top++; 57 sa[top]=a[i]; 58 } 59 sa[top+1]=a[1]; 60 return top; 61 } 62 int grahamb(int N) 63 {int i; 64 sort(b+1,b+N+1,cmp); 65 sort(b+2,b+N+1,cmp2); 66 top=0; 67 sb[++top]=b[1]; 68 if (N==1) return 1; 69 sb[++top]=b[2]; 70 for (i=3;i<=N;i++) 71 { 72 while (top>1&&cross(b[i]-sb[top-1],sb[top]-sb[top-1])>=0) top--; 73 top++; 74 sb[top]=b[i]; 75 } 76 sb[top+1]=b[1]; 77 return top; 78 } 79 bool cmpp(Node A,Node B) 80 { 81 lol t=cross((s[1]-A),(s[1]-B)); 82 if (t==0) return dist(s[1]-A)<dist(s[1]-B); 83 return t>0; 84 } 85 int grahams(int N) 86 {int i; 87 sort(s+1,s+N+1,cmp); 88 sort(s+2,s+N+1,cmpp); 89 top=0; 90 sta[++top]=s[1]; 91 if (N==1) return 1; 92 sta[++top]=s[2]; 93 for (i=3;i<=N;i++) 94 { 95 while (top>1&&cross(s[i]-sta[top-1],sta[top]-sta[top-1])>=0) top--; 96 top++; 97 sta[top]=s[i]; 98 } 99 sta[top+1]=s[1]; 100 return top; 101 } 102 bool cmp3(Node A,Node B) 103 { 104 return cross(A,B)>0||(cross(A,B)==0&&dist(A)<dist(B)); 105 } 106 lol find(Node A) 107 { 108 if(cross(A,sta[1])>0||cross(sta[top],A)>0) return 0; 109 lol ps=lower_bound(sta+1,sta+top+1,A,cmp3)-sta-1; 110 return cross((A-sta[ps]),(sta[ps%top+1]-sta[ps]))<=0; 111 } 112 void Minkowski() 113 { 114 for(lol i=1;i<n;i++) s1[i]=sa[i+1]-sa[i];s1[n]=sa[1]-sa[n]; 115 for(lol i=1;i<m;i++) s2[i]=sb[i+1]-sb[i];s2[m]=sb[1]-sb[m]; 116 top=1; 117 s[top]=sa[1]+sb[1]; 118 lol i=1,j=1; 119 while(i<=n&&j<=m) ++top,s[top]=s[top-1]+(cross(s1[i],s2[j])>=0?s1[i++]:s2[j++]); 120 while(i<=n) ++top,s[top]=s[top-1]+s1[i++]; 121 while(j<=m) ++top,s[top]=s[top-1]+s2[j++]; 122 } 123 int main() 124 {int i,j; 125 lol dx,dy; 126 cin>>n>>m>>q; 127 for (i=1;i<=n;i++) 128 scanf("%lld%lld",&a[i].x,&a[i].y); 129 for (i=1;i<=m;i++) 130 scanf("%lld%lld",&b[i].x,&b[i].y),b[i].x=-b[i].x,b[i].y=-b[i].y; 131 n=grahama(n); 132 m=grahamb(m); 133 Minkowski(); 134 top=grahams(top); 135 bs=sta[1]; 136 for (i=1;i<=top;i++) 137 sta[i]=sta[i]-bs; 138 139 for (i=1;i<=q;i++) 140 { 141 scanf("%lld%lld",&dx,&dy); 142 if (find((Node){dx,dy}-bs)) 143 printf("1\n"); 144 else printf("0\n"); 145 } 146 }