为啥我先三分位置再二分初始范围会错,而先二分范围再二分位置就是对的呢,范围随位置变化的函数应该是单峰的啊(比如位置越靠左,炸完右边的应该更难,需要的范围越大)
const int N=5e4+5;
int n;
ld where[N];
void read()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>where[i];
}
}
int pan(ld w,ld x)
{
int t=0;
for(;sgn(where[t+1]-w)<0;t++)
{
}
ld r=x,pos=w;
for(int i=t;i>=1;r--)
{
if(pos>r+where[i])
{
return -1;
}
for(;i>=1&&pos<=r+where[i];i--)
{
}
pos=where[i+1];
}
r=x,pos=w;
for(int i=t+1;i<=n;r--)
{
if(where[i]>r+pos)
{
return 1;
}
for(;i<=n&&where[i]<=r+pos;i++)
{
}
pos=where[i-1];
}
return 0;
}
bool check(ld w)
{
ld l=where[1],r=where[n];
for(;sgn(l-r)<0;)
{
ld mid=(l+r)/2;
int t=pan(mid,w);
if(t==1)
{
l=mid;
}else if(t==-1)
{
r=mid;
}else
{
return 1;
}
}
return 0;
}
ld solve()
{
sort(where+1,where+n+1);
ld l=0,r=where[n]-where[1];
for(;sgn(l-r)<0;)
{
ld mid=(l+r)/2;
if(check(mid))
{
r=mid;
}else
{
l=mid;
}
}
return l;
}
signed main()
{
read();
printf("%.1lf",solve());
}
const int N=5e4+5;
int n;
int where[N];
void read()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>where[i];
}
}
int di(ld x)
{
int l=1,r=n;
for(;l<r;)
{
int mid=(l+r+1)/2;
if(sgn(where[mid]-x)<=0)
{
l=mid;
}else
{
r=mid-1;
}
}
return l;
}
bool pan(ld w,ld x)
{
int l=di(w),r=l+1;
ld ll=w,lr=w;
ld f=x;
for(bool can=1;sgn(f)>=0&&(l>=1||r<=n)&&can;f-=1)
{
can=0;
ld xl=ll,xr=lr;
for(;l>=1&&sgn(abs(ll-where[l])-f)<=0;l--)
{
can=1;
xl=where[l];
}
for(;r<=n&&sgn(abs(lr-where[r])-f)<=0;r++)
{
can=1;
xr=where[r];
}
ll=xl;lr=xr;
}
return l<1&&r>n;
}
ld get_ans(ld w)
{
ld l=0,r=1e9;
for(;sgn(l-r)<0;)
{
ld mid=(l+r)/2;
if(pan(w,mid))
{
r=mid;
}else
{
l=mid;
}
}
return l;
}
ld solve()
{
sort(where+1,where+n+1);
n=unique(where+1,where+n+1)-(where+1);
ld l=0,r=1e9;
for(;sgn(l-r)<0;)
{
ld midl=l+(r-l)/3,midr=r-(r-l)/3;
if(sgn(get_ans(midl)-get_ans(midr))>0)
{
l=midl;
}else
{
r=midr;
}
}
return get_ans(l);
}
signed main()
{
read();
printf("%.1lf\n",solve());
}