• BZOJ 2564: 集合的面积


    传送门

    首先容易证明,$A+B$ 的凸包上的点集一定是 $A$ 凸包上的某个点 加上 $B$ 凸包上的某个点

    所以先求出 $A,B$ 的两个凸包,然后按极角维护两个指针 $la,lb$ 分别指向 $A,B$ 目前极角最小的点

    首先 $A,B$ 最左的点一定在 $A+B$ 的凸包上

    然后考虑移动指针 $lb$,发现随着 $lb$ 的增加,最优的 $la$ 是单调不降的(这个画个图会很容易理解)

    所以利用单调性我们就可以把枚举凸包点的复杂度降到 $O(n)$

    其实这就是求点集的闵可夫斯基和的凸包的做法,新操作 $get$

    具体实现在代码,细节还是要注意的,因为题目中点都是整数,而且最后答案也一定是整数,所以直接全 $long long$ 就行

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7;
    struct poi {
        ll x,y;
        poi (ll a=0,ll b=0) { x=a,y=b; }
        inline poi operator + (const poi &tmp) const {
            return poi(x+tmp.x,y+tmp.y);
        }
        inline poi operator - (const poi &tmp) const {
            return poi(x-tmp.x,y-tmp.y);
        }
        inline bool operator < (const poi &tmp) const {
            return x-tmp.x!=0 ? x<tmp.x : y<tmp.y;
        }
    }A[N],B[N],st[N];
    inline ll Cross(poi A,poi B) { return A.x*B.y-A.y*B.x; }
    inline ll Dot(poi A,poi B) { return A.x*B.x+A.y*B.y; }
    inline ll Len(poi A) { return sqrt(Dot(A,A)); }
    inline bool cmp(poi A,poi B) { return Cross(A,B)>0|| (Cross(A,B)==0&&Len(A)<Len(B)); }
    void Tubao(poi *P,int &tot)
    {
        sort(P+1,P+tot+1); for(int i=tot;i>=1;i--) P[i]=P[i]-P[1];
        sort(P+1,P+tot+1,cmp); int Top=0;
        for(int i=1;i<=tot;st[++Top]=P[i],i++)
            while( Top>1 && Cross(P[i]-st[Top-1],st[Top]-st[Top-1])>=0 ) Top--;
        tot=Top; for(int i=1;i<=tot;i++) P[i]=st[i];
    }
    int n,m;
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++) A[i].x=read(),A[i].y=read();
        for(int i=1;i<=m;i++) B[i].x=read(),B[i].y=read();
        Tubao(A,n); Tubao(B,m);
        int Top=1,la=1,lb=1; st[Top]=A[1]+B[1];
        while(la<=n||lb<=m)
        {
            poi p1=A[(la-1)%n+1]+B[lb%m+1],p2=A[la%n+1]+B[(lb-1)%m+1];
            if(Cross(p1-st[Top],p2-st[Top])>=0) lb++,st[++Top]=p1;
            else la++,st[++Top]=p2;
        }
        ll res=0; for(int i=2;i<Top;i++) res+=Cross(st[i]-st[1],st[i+1]-st[1]);
        printf("%lld
    ",res);
        return 0;
    }
  • 相关阅读:
    Java基于Socket文件传输示例
    mysql 改变编码
    POI应用:利用word模板批量生成word文档(java中word文档的读写)
    Win 7—FTP服务器配置
    Chrome 快捷键
    JAVA中使用FTPClient上传下载 java利用ftp协议上传文件(by me)
    JAVA中使用FTPClient上传下载
    如何去除TD之间的空隙
    较丰富的教程
    输入年月 返回当月天数.html
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11441703.html
Copyright © 2020-2023  润新知