bzoj2564 集合的面積


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)。

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

Sample Output

18
數據規模和約定
對於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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM