记录编号 360550 评测结果 AAAAAAAAAA
题目名称 [NOI 2007]货币兑换 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.648 s
提交时间 2016-12-30 08:39:32 内存使用 30.81 MiB
显示代码纯文本
#include<cstdio>
typedef double db;
const int N=1e5+10;
int n,s;db a[N],b[N],rate[N],ans[N];
struct point{
	db x,y;
	point(db X=0,db Y=0){x=X;y=Y;}
}p[N],q[N],P[N];
db abs(db x){return x>0?x:-x;}
db max(db x,db y){return x>y?x:y;}
db k(point &x,point &y){
	if (abs(x.x-y.x)<=1e-9) return x.y<y.y?1e9:-1e9;
	return (x.y-y.y)/(x.x-y.x);
}
struct opt{
	db k;int id;
	opt(db K=0,int ID=0){id=ID;k=K;}
}T[20][N];//归并树 
void mergesort(int h,int l,int r){//建立归并树 
	if (l==r) return;
	int mid=(l+r)>>1;
	opt *a=T[h],*b=T[h+1];
	for (int i=l;i<=r;i++) b[i]=a[i];
	mergesort(h+1,l,mid);
	mergesort(h+1,mid+1,r);
	int pos=l,i=l,j=mid+1;
	while (i<=mid&&j<=r) a[pos++]=(b[i].k>b[j].k?b[i++]:b[j++]);
	for (;i<=mid;a[pos++]=b[i++]);
	for (;j<=r;a[pos++]=b[j++]);
}
void solve(int h,int l,int r){//陈丹琦分治 
	if (l==r){
		ans[l]=max(ans[l],ans[l-1]);
		db y=ans[l]/(a[l]*rate[l]+b[l]),x=y*rate[l];
		p[l]=point(x,y);
		return;
	}
	int mid=(l+r)>>1,head=1,tail=0;
	opt *A=T[h];
	solve(h+1,l,mid);
	for (int i=l;i<=mid;i++){
		for (;head<tail&&k(q[tail-1],q[tail])<k(q[tail],p[i]);tail--);
		q[++tail]=p[i];
	}
	for (int i=mid+1;i<=r;i++){
		for (;head<tail&&k(q[head],q[head+1])>A[i].k;head++);
		int id=A[i].id;
		ans[id]=max(ans[id],q[head].x*a[id]+q[head].y*b[id]);
	}
	solve(h+1,mid+1,r);
	int pos=l,i=l,j=mid+1;
	while (i<=mid&&j<=r) P[pos++]=(p[i].x<p[j].x?p[i++]:p[j++]);
	for (;i<=mid;P[pos++]=p[i++]);
	for (;j<=r;P[pos++]=p[j++]);
	for (i=l;i<=r;p[i]=P[i],i++);
}
int main()
{
	freopen("cash.in","r",stdin);
	freopen("cash.out","w",stdout);
	scanf("%d%d",&n,&s);
	ans[0]=s;
	for (int i=1;i<=n;i++){
		scanf("%lf%lf%lf",&a[i],&b[i],&rate[i]);
		if (a[i]==0) a[i]=1e-9;
		if (b[i]==0) b[i]=1e-9;
		if (rate[i]==0) rate[i]=1e-9;
		T[0][i]=opt(-a[i]/b[i],i);
	}
	mergesort(0,1,n);
	solve(1,1,n);
	printf("%.3lf\n",ans[n]);
	return 0;
}