Description
對於一個平面上點的集合P={(x
i,y
i )},定義集合P的面積F(P)為點集P的凸包的面積。
對於兩個點集A和B,定義集合的和為:
A+B={(x i A+x j B,y i A+y j B ):(x i A,y i A )∈A,(x j B,y j B )∈B}
現在給定一個N個點的集合A和一個M個點的集合B,求2F(A+B)。
對於兩個點集A和B,定義集合的和為:
A+B={(x i A+x j B,y i A+y j B ):(x i A,y i A )∈A,(x j B,y j B )∈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。
數據規模和約定
對於30%的數據滿足N ≤ 200,M ≤ 200;
對於100%的數據滿足N ≤ 10^5,M ≤ 10^5,|xi|, |yi| ≤ 10^8。
正解:$Minkowski$和。
$Minkowski$和,就是題面的這個東西。。
分別求出兩個點集的凸包,然后貪心地加點就行。
首先,$A$凸包和$B$凸包的第一個點的和肯定會在最終的凸包里。
然后我們設$A$凸包到了$i$點,$B$凸包到了$j$點。
如果$a[i+1]+b[j]$比$a[i]+b[j+1]$更凸,那么就用$A$凸包更新,否則用$B$凸包更新。
最后求出的這個就是新凸包,直接用叉積算面積就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define N (500010) 6 7 using namespace std; 8 9 struct point{ 10 ll x,y; 11 il point operator + (const point &a) const{ 12 return (point){x+a.x,y+a.y}; 13 } 14 il point operator - (const point &a) const{ 15 return (point){x-a.x,y-a.y}; 16 } 17 }p[N],t1[N],t2[N],st[N]; 18 19 int n,m,top; 20 ll S; 21 22 il int gi(){ 23 RG int x=0,q=1; RG char ch=getchar(); 24 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 25 if (ch=='-') q=-1,ch=getchar(); 26 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 27 return q*x; 28 } 29 30 il int cmp(const point &a,const point &b){ 31 if (a.x==b.x) return a.y<b.y; return a.x<b.x; 32 } 33 34 il ll cross(RG point a,RG point b){ return a.x*b.y-a.y*b.x; } 35 36 il void graham(point *p,point *t,RG int n){ 37 sort(p+1,p+n+1,cmp); 38 for (RG int i=1;i<=n;++i){ 39 while (top>=2 && cross(p[i]-t[top-1],t[top]-t[top-1])>=0) --top; 40 t[++top]=p[i]; 41 } 42 for (RG int i=n-1,la=top;i>=1;--i){ 43 while (top>la && cross(p[i]-t[top-1],t[top]-t[top-1])>=0) --top; 44 t[++top]=p[i]; 45 } 46 --top; return; 47 } 48 49 int main(){ 50 #ifndef ONLINE_JUDGE 51 freopen("area.in","r",stdin); 52 freopen("area.out","w",stdout); 53 #endif 54 n=gi(),m=gi(); 55 for (RG int i=1;i<=n;++i) p[i].x=gi(),p[i].y=gi(); graham(p,t1,n),n=top,top=0; 56 for (RG int i=1;i<=m;++i) p[i].x=gi(),p[i].y=gi(); graham(p,t2,m),m=top,top=0; 57 st[top=1]=t1[1]+t2[1]; 58 for (RG int i=1,j=1;i<=n || j<=m;){ 59 RG point x=t1[(i-1)%n+1]+t2[j%m+1],y=t1[i%n+1]+t2[(j-1)%m+1]; 60 if (cross(x-st[top],y-st[top])>=0) st[++top]=x,++j; else st[++top]=y,++i; 61 } 62 for (RG int i=2;i<top;++i) S+=cross(st[i]-st[1],st[i+1]-st[1]); cout<<S; return 0; 63 }