• bzoj2564 集合的面积


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

    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 }
  • 相关阅读:
    .net 中ifram的session过期,跳转到登录页面
    新建物料组!
    WCF学习系列(1)
    WCF学习系列(4)————数据协定
    AX中操作Excel
    WCF学习系列(3)————承载
    简单的库存模型组
    博弈_ZOJ3591_序列中子序列异或值大于0.cpp
    zoj2527_求最长等差数列
    第二次周日赛
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7470202.html
Copyright © 2020-2023  润新知