[BZOJ2338][HNOI2011]数矩形(计算几何)

来源:互联网 发布:linux动态获取ip地址 编辑:程序博客网 时间:2024/05/25 18:09

题目描述

传送门

题目大意:给出二维平面上的n个点,求一个最大的矩形,它的顶点都在给出的点上。

题解

首先预处理出所有的线段,中点相同、长度相同的两条线段可以组成一个合法的矩形
将所有的线段按照一维中点、一维长度、一维斜率排序,对于中点相同、长度相同的线段必定在一段区间里,并且对于一条线段,取到最大值的另一条线段单峰,用两个指针扫一下就行了

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define db double#define LL long long#define N 1505const LL inf=1e18;int n,cnt;LL ans,x[N],y[N];struct Seg{    int id,jd;    LL x,y,len;    double k;}s[N*N];LL qr(LL x){return x*x;}int cmp(Seg a,Seg b){    return a.x<b.x||(a.x==b.x&&a.y<b.y)||(a.x==b.x&&a.y==b.y&&a.len<b.len)||(a.x==b.x&&a.y==b.y&&a.len==b.len&&a.k<b.k);}LL Abs(LL x){return (x>0)?x:-x;}LL Area(Seg a,Seg b){    LL vx=x[b.id]-x[a.id],vy=y[b.id]-y[a.id];    LL wx=x[b.jd]-x[a.id],wy=y[b.jd]-y[a.id];    return Abs(vx*wy-vy*wx);}int main(){    scanf("%d",&n);    for (int i=1;i<=n;++i) scanf("%lld%lld",&x[i],&y[i]);    for (int i=1;i<=n;++i)        for (int j=i+1;j<=n;++j)        {            ++cnt;            s[cnt].id=i,s[cnt].jd=j;            s[cnt].x=x[i]+x[j],s[cnt].y=y[i]+y[j];            s[cnt].len=qr(x[i]-x[j])+qr(y[i]-y[j]);            if (x[i]==x[j]) s[cnt].k=inf;            else s[cnt].k=((db)y[i]-(db)y[j])/((db)x[i]-(db)x[j]);        }    sort(s+1,s+cnt+1,cmp);    for (int i=1,j;i<=cnt;i=j+1)    {        j=i;        while (s[j].x==s[i].x&&s[j].y==s[i].y&&s[j].len==s[i].len)            ++j;        --j;        int l=i,r=i;        while (l<=j)        {            r=max(r,l);            while (r<j&&Area(s[l],s[r])<=Area(s[l],s[r+1]))                ++r;            ans=max(ans,Area(s[l],s[r]));            ++l;        }    }    printf("%lld\n",ans);}
0 0
原创粉丝点击