bzoj 1670 Building the Moat护城河的挖掘 —— 凸包
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1670
单调栈维护凸包即可,用叉积判断;
维护上凸壳,然后把所有点的纵坐标翻转再求上凸壳即可,要注意排序规则略有变化。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef double db; int const xn=5005; db const eps=1e-8; int n,top,mx; db ans; struct N{ db x,y; N(db x=0,db y=0):x(x),y(y) {} bool operator < (const N &b) const {return x<b.x||(x==b.x&&y<b.y);} }p[xn],sta[xn]; bool cmp(N a,N b){return a.x<b.x||(a.x==b.x&&a.y>b.y);} N operator - (const N &a,const N &b){return N(a.x-b.x,a.y-b.y);} int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return f?ret:-ret; } int maxx(int x,int y){return x<y?y:x;} db sqr(db x){return x*x;} db cross(N a,N b){return a.x*b.y-a.y*b.x;} db len(N a){return sqrt(sqr(a.x)+sqr(a.y));} db dis(N a,N b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} int dmp(db x){if(fabs(x)<=eps)return 0; return x>eps?1:-1;} void work() { top=0; for(int i=1;i<=n;i++) { while(top>1&&dmp(cross(sta[top]-sta[top-1],p[i]-sta[top]))>=0)top--; sta[++top]=p[i]; } while(top>1)ans+=len(sta[top]-sta[top-1]),top--; } int main() { n=rd(); mx=0; for(int i=1;i<=n;i++)p[i].x=rd(),p[i].y=rd(),mx=maxx(mx,p[i].y); sort(p+1,p+n+1); work(); for(int i=1;i<=n;i++)p[i].y=mx-p[i].y+1; sort(p+1,p+n+1,cmp);// work(); printf("%.2f\n",ans); return 0; }