bzoj1069: [SCOI2007]最大土地面积

真搞笑,网上的人太能带节奏了,还以为是旋转卡(qia ka)壳(ke qiao)

凸包完了直接暴力枚举对角的两个点,然后相当于两个区间分别找一个令和对角线组成的三角形最大的点,有单调性不用扫直接O(1)了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-8;
double sqr(double x){return x*x;}

struct point{double x,y;}p[2100];
double dis(point p1,point p2){return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}
double multi(point p1,point p2,point p0)
{
    int x1,y1,x2,y2;
    x1=p1.x-p0.x;
    y1=p1.y-p0.y;
    x2=p2.x-p0.x;
    y2=p2.y-p0.y;
    return x1*y2-x2*y1;
}

int n;
bool cmp(point p1,point p2)
{
    double d=multi(p1,p2,p[1]);
    if(fabs(d)<=eps)return dis(p1,p[1])<dis(p2,p[1]);
    else return d>0;
}
int top,sta[1100000];
void graham()
{
    sort(p+2,p+n+1,cmp);
    top=0;sta[++top]=1,sta[++top]=2;
    double g;
    for(int i=3;i<=n;i++)
    {
        while(top>=2)
        {
            g=multi(p[sta[top]],p[i],p[sta[top-1]]);
            if(g<0||fabs(g)<=eps)top--;
            else break;
        }
        sta[++top]=i;
    }
}
int MOD(int x){return (x-1)%top+1;}
double rch()
{
    double ans=0;int a,b;
    for(int i=1;i<=top-2;i++)
    {
        a=MOD(i+1),b=MOD(i+3);
        for(int j=i+2;j<=top;j++)
        {
            while(MOD(a+1)!=j&&multi(p[sta[i]],p[sta[a]],p[sta[j]])<multi(p[sta[i]],p[sta[MOD(a+1)]],p[sta[j]]))a=MOD(a+1);
            while(MOD(b+1)!=i&&multi(p[sta[j]],p[sta[b]],p[sta[i]])<multi(p[sta[j]],p[sta[MOD(b+1)]],p[sta[i]]))b=MOD(b+1);
            ans=max(ans,(multi(p[sta[a]],p[sta[j]],p[sta[i]])+multi(p[sta[b]],p[sta[i]],p[sta[j]]))/2.0);
        }
    }
    printf("%.3lf\n",ans);
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&p[i].x,&p[i].y);
        if(p[i].y<p[1].y||(p[i].y==p[1].y&&p[i].x<p[1].x))
            swap(p[i],p[1]);
    }
    graham();
    rch();
    
    return 0;
}

 

posted @ 2019-01-14 21:22  AKCqhzdy  阅读(144)  评论(0编辑  收藏  举报