有关两种二分方法
查看原帖
有关两种二分方法
822769
Colier楼主2023/10/26 20:40

为啥我先三分位置再二分初始范围会错,而先二分范围再二分位置就是对的呢,范围随位置变化的函数应该是单峰的啊(比如位置越靠左,炸完右边的应该更难,需要的范围越大)

正确的:

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());
}
2023/10/26 20:40
加载中...