bzoj 2564 集合的面积
Description
对于一个平面上点的集合P={(xi,yi )},定义集合P的面积F(P)为点集P的凸包的面积。
对于两个点集A和B,定义集合的和为:
A+B={(xiA+xjB,yiA+yjB ):(xiA,yiA )∈A,(xjB,yjB )∈B}
现在给定一个N个点的集合A和一个M个点的集合B,求2F(A+B)。
对于两个点集A和B,定义集合的和为:
A+B={(xiA+xjB,yiA+yjB ):(xiA,yiA )∈A,(xjB,yjB )∈B}
现在给定一个N个点的集合A和一个M个点的集合B,求2F(A+B)。
Input
第一行包含用空格隔开的两个整数,分别为N和M;
第二行包含N个不同的数对,表示A集合中的N个点的坐标;
第三行包含M个不同的数对,表示B集合中的M个点的坐标。
Output
一共输出一行一个整数,2F(A+B)。
Sample Input
4 5
0 0 2 1 0 1 2 0
0 0 1 0 0 2 1 2 0 1
0 0 2 1 0 1 2 0
0 0 1 0 0 2 1 2 0 1
Sample Output
18
数据规模和约定
对于30%的数据满足N ≤ 200,M ≤ 200;
对于100%的数据满足N ≤ 10^5,M ≤ 10^5,|xi|, |yi| ≤ 10^8。
分别求出两个点集的凸包,然后贪心地加点就行。
A和B凸包第一个点肯定在答案里
然后贪心,如果A到了i,B到了j
显然如果A[i+1]+B[j]比A[i]+B[j+1]更凸,也就是在右边,那么就i+1,否则j+1
这样构造出的新凸包即为答案
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 struct point 9 { 10 lol x,y; 11 }p[200001],s[3][200001],sta[1000001]; 12 int n,m,C,top; 13 lol ans; 14 lol cross(point a,point b) 15 { 16 return a.x*b.y-a.y*b.x; 17 } 18 point operator -(point a,point b) 19 { 20 return (point){a.x-b.x,a.y-b.y}; 21 } 22 point operator +(point a,point b) 23 { 24 return (point){a.x+b.x,a.y+b.y}; 25 } 26 bool cmp(point a,point b) 27 { 28 return (a.y<b.y)||(a.y==b.y&&a.x<b.x); 29 } 30 lol dist(point a) 31 { 32 return a.x*a.x+a.y*a.y; 33 } 34 bool cmp2(point a,point b) 35 { 36 lol t=cross((p[1]-a),(p[1]-b)); 37 if (t==0) return dist(p[1]-a)<dist(p[1]-b); 38 return t>0; 39 } 40 int graham(int N,int c) 41 {int i; 42 int C=c; 43 sort(p+1,p+N+1,cmp); 44 sort(p+2,p+N+1,cmp2); 45 top=0; 46 s[c][++top]=p[1];s[c][++top]=p[2]; 47 for (i=3;i<=N;i++) 48 { 49 while (top>1&&cross(p[i]-s[c][top-1],s[c][top]-s[c][top-1])>=0) top--; 50 ++top; 51 s[c][top]=p[i]; 52 } 53 return top; 54 } 55 int main() 56 {int i,j; 57 cin>>n>>m; 58 for (i=1;i<=n;i++) 59 { 60 scanf("%lld%lld",&p[i].x,&p[i].y); 61 } 62 n=graham(n,1); 63 for (i=1;i<=m;i++) 64 { 65 scanf("%lld%lld",&p[i].x,&p[i].y); 66 } 67 m=graham(m,2); 68 sta[top=1]=s[1][1]+s[2][1]; 69 for (i=1,j=1;i<=n||j<=m;) 70 { 71 point x=s[1][(i-1)%n+1]+s[2][j%m+1],y=s[1][i%n+1]+s[2][(j-1)%m+1]; 72 if (cross(x-sta[top],y-sta[top])>=0) 73 sta[++top]=x,j++; 74 else sta[++top]=y,i++; 75 } 76 for (i=2;i<top;i++) 77 ans+=cross(sta[i]-sta[1],sta[i+1]-sta[1]); 78 printf("%lld",ans); 79 }