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; }
pain and happy in the cruel world.