luogu4166 最大土地面积 (旋转卡壳)
首先这样的点一定在凸包上
然后旋转卡壳就可以
具体来说,枚举对角线的一个端点,另一个端点在凸包上转,剩下两个点就是一个叉积最大一个最小,而这两个点也是跟着转的
所以是$O(N^2)$
1 #include<bits/stdc++.h> 2 #include<tr1/unordered_map> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 using namespace std; 6 typedef long long ll; 7 typedef unsigned long long ull; 8 typedef pair<int,int> pa; 9 const int maxn=2005; 10 11 inline ll rd(){ 12 ll x=0;char c=getchar();int neg=1; 13 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 14 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 15 return x*neg; 16 } 17 18 struct Vec{ 19 double x,y; 20 Vec(double a=0,double b=0){x=a,y=b;} 21 }p[maxn],stk[maxn]; 22 inline Vec operator -(Vec a,Vec b){return Vec(a.x-b.x,a.y-b.y);} 23 inline double operator *(Vec a,Vec b){return a.x*b.y-a.y*b.x;} 24 int N,sh; 25 26 inline bool cmp(Vec a,Vec b){ 27 double x=a*b; 28 return x?x>0:fabs(a.x)<fabs(b.x); 29 } 30 31 inline int ne(int x,int y=1){return x+y>sh?x+y-sh:x+y;} 32 33 int main(){ 34 //freopen("","r",stdin); 35 N=rd(); 36 for(int i=1;i<=N;i++){ 37 scanf("%lf%lf",&p[i].x,&p[i].y); 38 if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[1].y)) swap(p[i],p[1]); 39 } 40 for(int i=N;i;i--) p[i]=p[i]-p[1]; 41 sort(p+1,p+N+1,cmp); 42 for(int i=1;i<=N;i++){ 43 while(sh>1&&(stk[sh]-stk[sh-1])*(p[i]-stk[sh-1])<=0) sh--; 44 stk[++sh]=p[i]; 45 } 46 double ans=0; 47 for(int i=1;i<=sh;i++){ 48 int a=ne(i,1),b=ne(i,2); 49 for(int j=ne(i,2);ne(j)!=i;j=ne(j)){ 50 while((stk[ne(a)]-stk[i])*(stk[j]-stk[i])>=(stk[a]-stk[i])*(stk[j]-stk[i])) a=ne(a); 51 while((stk[j]-stk[i])*(stk[ne(b)]-stk[i])>=(stk[j]-stk[i])*(stk[b]-stk[i])) b=ne(b); 52 ans=max(ans,((stk[a]-stk[i])*(stk[j]-stk[i])+(stk[j]-stk[i])*(stk[b]-stk[i]))/2); 53 } 54 } 55 printf("%.3lf\n",ans); 56 return 0; 57 }