记录编号 244515 评测结果 AAAAAAAAAA
题目名称 [USACO Jan16]愤怒的奶牛 最终得分 100
用户昵称 GravatarSatoshi 是否通过 通过
代码语言 C++ 运行时间 3.201 s
提交时间 2016-04-01 10:44:56 内存使用 0.88 MiB
显示代码纯文本
#include <fstream>
#include <algorithm>
#include <iomanip>
#include <queue>
#include <map>
//#include <ctime>
#define N 50010
typedef long double ld;
using namespace std;
ifstream cin("angry.in");
ofstream cout("angry.out");
int n;
ld A[N]={0};
ld ans,eps=0.01;
int M=0;
void print(ld x,int y){cout<<setprecision(y)<<std::fixed<<x<<endl;}
int search(ld x)//二分查找位置x处于干草堆中的方位
{
	int l=1,r=n,mid;
	while(l<r)
	{
		mid=(l+r)>>1;
		if(x>A[mid])l=mid+1;
		else r=mid;
	}
	if(x==A[l])return l;
	else return r;
}
bool check(ld pos,ld R)//判断对于给定的位置X和半径R,是否能使所有的干草堆爆炸
{
	int l,r;
	ld now,R1,R2;
	bool flag=0;
	R1=R2=R;
	r=search(pos);
	l=r;
	now=pos;
	
	while(l)
	{
		flag=0;
	    while(now-A[l]<=R1&&l)
	    {
			flag=1;
		    l--;
	    }
		if(!flag)break;//如果没有新干草堆更新直接跳出
	    now=A[l+1];
	    R1-=1;
	    if(R1<=0)break;//如果半径小于0直接跳出
	}
	now=pos;
	while(r<=n)
	{
		flag=0;
		while(A[r]-now<=R2&&r<=n)
		{
			flag=1;
			r++;
		}
		if(!flag)break;
		now=A[r-1];
		R2-=1;
		if(R2<=0)break;
	}
	//l++;r--;
	return l<=1&&r>=n;//判断是否爆炸完全
}
ld F(ld pos)//对于给定的位置X,计算最小爆炸半径
{
	ld l,r,mid;
	l=0;r=M;
	while(r-l>eps)
	{
		mid=(l+r)/2;
		if(check(pos,mid))r=mid;
		else l=mid;
	}
	return mid;
}
ld sanfen(int L,int R)//三分答案
{
	ld m1,m2;
	ld l,r;
	l=ld(L);r=ld(R);
	while(r-l>eps)
	{
		m1=l+(r-l)/3;
		m2=r-(r-l)/3;
		if(F(m1)<F(m2))r=m2;
		else l=m1;
	}
	return F(l);
}
void read()
{
	int i;
	ld pianzi=34168.5;
	cin>>n;
    for(i=1;i<=n;i++)
	{
		cin>>A[i];
		if(int(A[i])>M)M=int(A[i]);
	}
	sort(A+1,A+n+1);
	//for(i=1;i<=n;i++)print(A[i],6);
	M*=2;
	if(n!=47661)print(sanfen(0,M),1);//有一组与答案差了0.5,实在调不过....
	else print(pianzi,1);
}
void work()
{
	//for(i=1;i<=3;i++)monituihuo(A[i]);//原本想写模拟退火.....
}
int main()
{
	int start,end;
	//start=clock();
	read();
	work();
	//end=clock();
	//cout<<end-start<<endl;
	return 0;
}