正解:半平面交
但是我们可以发现这么多线搞半平面的交集是一个半凸壳,没错于是我们就可以借用某一道好像是最大可视面积(其实是HNOI2008水平可视直线)还是什么的题的做法直接维护这个图形
然后我们就可以在每条线的交点处计算上下差值,至于为什么是交点……简单动态规划的最优值一定在某一个端点处取得大概是这样(其实我们可以用单调性来证明,毕竟线性函数)
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<iomanip> #define LL long long #define LF double #define fo(i,a,b) for(int i=a;i<=b;i++) #define down(i,a,b) for(int i=a;i>=b;i--) using namespace std; #define N 305 #define eps 1e-8 struct P { double x,y; }d[N],l[N]; int n,m; LL read() { LL d=0,f=1;char s=getchar(); while (s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while (s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } LF operator*(P a,P b) { return a.x*b.y-a.y*b.x; } LF operator/(P a,P b) { return a.x*b.x+a.y*b.y; } P operator+(P a,P b) { P t; t.x=a.x+b.x; t.y=a.y+b.y; return t; } P operator-(P a,P b) { P t; t.x=a.x-b.x; t.y=a.y-b.y; return t; } bool operator==(P a,P b) { return (a.x==b.x)&&(a.y==b.y); } LF dis(P a,P b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y*b.y)*(a.y*b.y)); } P make(P a,P b) { P t; t.x=(b.y-a.y)/(b.x-a.x); t.y=a.y-a.x*t.x; return t; } bool sortcom(P a,P b) { if (fabs(a.x-b.x)<=eps) return a.y<b.y; return a.x<b.x; } double calx(int a,int b) { return (l[b].y-l[a].y)/(l[a].x-l[b].x); } double ans=0.0; int s[N],stop=0; double yup(double x) { double t=0.0; fo(i,1,stop) t=max(t,l[s[i]].x*x+l[s[i]].y); return t; } double ydown(double x) { int po=n; double t=0.0; fo(i,1,n-1) if (d[i].x<x&&x<d[i+1].x) { po=i; break; } if (po==n) return d[n].y; P lin=make(d[po],d[po+1]); t=lin.x*x+lin.y; return t; } double crossx(P a,P b) { return (b.y-a.y)/(a.x-b.x); } void checks() { fo(i,1,stop) cout<<l[s[i]].x<<' '<<l[s[i]].y<<endl; cout<<endl; } int main() { n=read(); fo(i,1,n) d[i].x=read(); fo(i,1,n) d[i].y=read(); fo(i,1,n-1) l[i]=make(d[i+1],d[i]); m=n-1; sort(l+1,l+m+1,sortcom); // checkl(); stop=0; s[++stop]=1; fo(i,2,m) { while (fabs(l[s[stop]].x-l[i].x)<=eps) stop--; while (stop>1&&calx(s[stop-1],s[stop])>=calx(s[stop],i)) stop--; s[++stop]=i; } cout<<setiosflags(ios::fixed); cout.precision(3); // checks(); ans=1e10; fo(i,1,n) { ans=min(ans,yup(d[i].x)-d[i].y); // cout<<ans<<endl; } // cout<<endl; fo(i,1,stop-1) { double t=crossx(l[s[i]],l[s[i+1]]); double ty=l[s[i]].x*t+l[s[i]].y; ans=min(ans,ty-ydown(t)); // cout<<ans<<endl; } cout<<ans<<endl; return 0; }