zoukankan      html  css  js  c++  java
  • bzoj2564集合的面积

    题目描述

      对于一个平面上点的集合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)。

     


    输入格式

     第一行包含用空格隔开的两个整数,分别为N和M;
      第二行包含N个不同的数对,表示A集合中的N个点的坐标;
      第三行包含M个不同的数对,表示B集合中的M个点的坐标。

     

    输出格式

     一共输出一行一个整数,2F(A+B)。


    数据规模和约定
      对于30%的数据满足N ≤ 200,M ≤ 200;
      对于100%的数据满足N ≤ 10^5,M ≤ 10^5,|xi|, |yi| ≤ 10^8。

    • 题解:

      • 如果一个点成为了和$A+B$的凸包,那么一定同时在$A$和$B$的凸包上;
      • 设$A+B$看成把凸包$A$平移后放在凸包$B$上,发现在两个凸包上组合成新的凸包的点对是单调的;
      • 类似$graham$维护两个指针;
      • 不太好说,附图,但是建议自己$YY$:
      •  1 #include<bits/stdc++.h>
         2 #define ll long long 
         3 using namespace std;
         4 const int N=200010;
         5 int n,m,cnt1,cnt2,Cnt;
         6 char gc(){
         7     static char*p1,*p2,s[1000000];
         8     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
         9     return (p1==p2)?EOF:*p1++;
        10 }
        11 int rd(){
        12     int x=0,f=1; char c=gc();
        13     while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
        14     while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=gc();}
        15     return x*f;
        16 }
        17 struct poi{
        18     int x,y;
        19     poi(int _x=0,int _y=0):x(_x),y(_y){};
        20     poi operator +(const poi&A)const{return poi(x+A.x,y+A.y);}
        21     poi operator -(const poi&A)const{return poi(x-A.x,y-A.y);}
        22     bool operator <(const poi&A)const{return x==A.x?y<A.y:x<A.x;}
        23 }p1[N],p2[N],q1[N],q2[N],Q[N];
        24 ll crs(poi A,poi B){return (ll)A.x*B.y-(ll)A.y*B.x;}
        25 void convex(poi *p,poi *q,int&tot,int&cnt){
        26     if(tot==1){q[cnt=1]=q[2]=p[1];return;}
        27     sort(p+1,p+tot+1);
        28     q[cnt=1]=p[1];
        29     for(int i=2;i<=tot;i++){
        30         while(cnt>1 && crs(q[cnt]-q[cnt-1],p[i]-q[cnt])<=0)cnt--;
        31         q[++cnt]=p[i];
        32     }
        33     int now=cnt;
        34     for(int i=tot-1;i;i--){
        35         while(cnt>now && crs(q[cnt]-q[cnt-1],p[i]-q[cnt])<=0)cnt--;
        36         q[++cnt]=p[i];
        37     }
        38     cnt--;
        39 }
        40 int main(){
        41     #ifndef ONLINE_JUDGE
        42     freopen("bzoj2564.in","r",stdin);
        43     freopen("bzoj2564.out","w",stdout);
        44     #endif
        45     n=rd();m=rd();
        46     for(int i=1;i<=n;i++)p1[i].x=rd(),p1[i].y=rd();
        47     for(int i=1;i<=m;i++)p2[i].x=rd(),p2[i].y=rd();
        48     convex(p1,q1,n,cnt1);
        49     convex(p2,q2,m,cnt2);
        50     int i,j;
        51     for(i=1,j=1;i<=cnt1;i++){
        52         Q[++Cnt]=q1[i]+q2[j];
        53         while(j<=cnt2&&crs(q2[j+1]-q2[j],q1[i+1]-q1[i])>0){
        54             Q[++Cnt]=q1[i]+q2[++j];
        55         }
        56     }
        57     for(;j<=cnt2+1;j++)Q[++Cnt]=q1[i]+q2[j];
        58     Cnt--;
        59     ll ans=0;
        60     for(i=2;i<Cnt;i++)ans += crs(Q[i]-Q[1],Q[i+1]-Q[1]);
        61     printf("%lld
        ",ans);
        62     return 0;
        63 }
        bzoj2564
  • 相关阅读:
    GIthub的小技巧
    C#中DateTime格式转换
    流程控制: if分支 while循环 for循环
    注释,输入,格式化输出,数据类型,运算符
    计算机原理简单了解
    day30
    day19
    day18 时间:time:,日历:calendar,可以运算的时间:datatime,系统:sys, 操作系统:os,系统路径操作:os.path,跨文件夹移动文件,递归删除的思路,递归遍历打印目标路径中所有的txt文件,项目开发周期
    day17跨文件夹导入模块,模块的两种被执行方式,包,直接使用包中模块,包的管理
    day16模块,导入模板完成的三件事,起别名,模块的分类,模块的加载顺序,环境变量,from...import语法导入,from...import *,链式导入,循环导入
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10269970.html
Copyright © 2011-2022 走看看