zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    【codecombat】 试玩全攻略 第二章 边远地区的森林 一步错
    【codecombat】 试玩全攻略 第十八关 最后的kithman族
    【codecombat】 试玩全攻略 第二章 边远地区的森林 woodlang cubbies
    【codecombat】 试玩全攻略 第二章 边远地区的森林 羊肠小道
    【codecombat】 试玩全攻略 第十七关 混乱的梦境
    【codecombat】 试玩全攻略 第二章 边远地区的森林 林中的死亡回避
    【codecombat】 试玩全攻略 特别关:kithguard斗殴
    【codecombat】 试玩全攻略 第二章 边远地区的森林 森林保卫战
    【codecombat】 试玩全攻略 第二章 边远地区的森林
    实验3 类和对象||
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7470202.html
Copyright © 2011-2022 走看看