[BZOJ 2338][HNOI 2011]数矩形(计算几何)

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=2338

思路

一个很显然的 O(n4)abcd ,这个做法很麻烦,而且很慢,有一个 O(n2)线O(n2)线O(nlogn)线线O(n2)线2

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>

#define MAXN 1520

using namespace std;

typedef long long int LL;

int n;

struct Point
{
    LL x,y;
    Point(){}
    Point(LL _x,LL _y) : x(_x),y(_y){}
}points[MAXN];

bool operator==(Point a,Point b)
{
    return a.x==b.x&&a.y==b.y;
}

bool operator<(Point a,Point b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}

bool operator>(Point a,Point b)
{
    if(a.x==b.x) return a.y>b.y;
    return a.x>b.x;
}

Point operator+(Point a,Point b)
{
    return Point(a.x+b.x,a.y+b.y);
}

Point operator-(Point a,Point b)
{
    return Point(a.x-b.x,a.y-b.y);
}

LL operator*(Point a,Point b)
{
    return a.x*b.y-a.y*b.x;
}

struct Line
{
    int a,b; //线段的两个端点
    LL len;
    Point mid;
    Line(){}
    Line(int _a,int _b,LL _len,Point _mid):a(_a),b(_b),len(_len),mid(_mid){}
}lines[MAXN*MAXN];

int cnt=0; //对角线总数

LL dist(Point a,Point b) //求点a与点b之间的距离
{
    return (LL)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

LL max(LL a,int b)
{
    if(a>b) return a;
    return b;
}

bool operator==(Line a,Line b)
{
    return a.len==b.len&&a.mid==b.mid;
}

bool operator<(Line a,Line b)
{
    if(a.len==b.len) return a.mid<b.mid;
    return a.len<b.len;
}

int main()
{
    LL ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&points[i].x,&points[i].y);
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
            lines[++cnt]=Line(i,j,dist(points[i],points[j]),points[i]+points[j]);
    sort(lines+1,lines+cnt+1);
    for(int i=1;i<=cnt;i++)
        for(int j=i-1;j&&lines[i]==lines[j];j--) //为了不重复计算,只数下标小于i的那部分对角线
            ans=max(ans,abs((points[lines[i].a]-points[lines[j].a])*(points[lines[i].a]-points[lines[j].b])));
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:([BZOJ 2338][HNOI 2011]数矩形(计算几何))