bzoj 2564 集合的面积

Description

  对于一个平面上点的集合P={(xi,yi )},定义集合P的面积F(P)为点集P的凸包的面积。
  对于两个点集AB,定义集合的和为:
  A+B={(xiA+xjB,yiA+yjB ):(xiA,yiA )A,(xjB,yjB )B}
  现在给定一个N个点的集合A和一个M个点的集合B,求2F(A+B)
 

Input

 第一行包含用空格隔开的两个整数,分别为NM
  第二行包含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。

分别求出两个点集的凸包,然后贪心地加点就行。

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 }

 

posted @ 2018-01-12 17:05  Z-Y-Y-S  阅读(699)  评论(0编辑  收藏  举报