BZOJ4570: [Scoi2016]妖怪

答案打出来发现是关于a/b的单峰函数,直接三分,复杂度$O(nlogw)$。

然后T了……卡常数……

显然最大值在右上凸壳上,于是先跑个凸包。

然后上凸壳上的点数<=4……

然后就过了这什么破题什么破数据……

#include<bits/stdc++.h>
using namespace std;
typedef double flo;
typedef long long ll;
const int N=1e6;
struct buf{
	char z[3<<23],*s;
	buf():s(z){z[fread(z,1,sizeof z,stdin)]=0;}
	operator int(){
		int x=0;
		while(*s<48)++s;
		while(*s>47)
			x=x*10+*s++-48;
		return x;
	}
}it;
struct vec{int x,y;};
vec c[N],r[N];
ll det(vec a,vec b){
	return(ll)a.x*b.y-(ll)a.y*b.x;
}
vec operator-(vec a,vec b){
	vec c={a.x-b.x,a.y-b.y};
	return c;
}
bool operator<(vec a,vec b){
	return a.x<b.x||a.x==b.x&&a.y<b.y;
}
int n,m;
flo cal(flo k){
	flo s=-1e18;
	for(int i=0;i<m;++i)
		s=max(s,r[i].x*(k+1)+r[i].y*(1/k+1));
	return s;
}
int main(){
	n=it;
	for(int i=0;i<n;++i)
		c[i].x=it,c[i].y=it;
	sort(c,c+n);
	for(int i=n-1;~i;--i){
		while(m>1&&det(c[i]-r[m-1],c[i]-r[m-2])>=0)--m;
		r[m++]=c[i];
	}
	flo s1=1e-4,s2=1e4;
	while(s2-s1>1e-12){
		flo s3=s1+(s2-s1)/3;
		flo s4=s2-(s2-s1)/3;
		cal(s3)<cal(s4)?s2=s4:s1=s3;
	}
	printf("%.4f\n",cal(s1));
}
posted @ 2017-03-22 15:56  f321dd  阅读(321)  评论(0编辑  收藏  举报