记录编号 373284 评测结果 AAAAAAAAAA
题目名称 [NOI 2007]货币兑换 最终得分 100
用户昵称 GravatarAntiLeaf 是否通过 通过
代码语言 C++ 运行时间 0.542 s
提交时间 2017-02-20 17:43:13 内存使用 16.69 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=100010;
const long double eps=1e-7;
void mergesort(int,int,int);
int CDQ(int,int,int);
long double getk(int,int);
long double w(int,int);
long double A[maxn],B[maxn],R[maxn],f[maxn],x[maxn],y[maxn],k[maxn];
double tmp;
int n,t[20][maxn],a[maxn],s[maxn];
int main(){
	freopen("cash.in","r",stdin);
	freopen("cash.out","w",stdout);
	scanf("%d%lf",&n,&tmp);
	f[1]=tmp;
	for(int i=1;i<=n;i++){
		scanf("%lf",&tmp);
		A[i]=tmp;
		scanf("%lf",&tmp);
		B[i]=tmp;
		scanf("%lf",&tmp);
		R[i]=tmp;
		k[i]=B[i]/A[i];
	}
	mergesort(1,n,0);
	CDQ(1,n,1);
	printf("%.3lf",(double)f[n]);
	return 0;
}
void mergesort(int l,int r,int d){
	if(l>=r){
		t[d][l]=l;
		return;
	}
	int mid=(l+r)>>1;
	mergesort(l,mid,d+1);
	mergesort(mid+1,r,d+1);
	int i=l,j=mid+1,p=l;
	while(i<=mid&&j<=r){
		if(k[t[d+1][i]]<=k[t[d+1][j]])t[d][p++]=t[d+1][i++];
		else t[d][p++]=t[d+1][j++];
	}
	while(i<=mid)t[d][p++]=t[d+1][i++];
	while(j<=r)t[d][p++]=t[d+1][j++];
}
int CDQ(int l,int r,int d){
	if(l>=r){
		a[l]=l;
		x[l]=f[l]/(A[l]*R[l]+B[l]);
		y[l]=-R[l]*x[l];
		f[l+1]=max(f[l+1],f[l]);
		return 1;
	}
	int mid=(l+r)>>1,cntl=CDQ(l,mid,d+1),i=l,j=mid+1;
	while(i<l+cntl-1&&j<=r){
		if(getk(a[i],a[i+1])-eps<k[t[d][j]])i++;
		else{
			f[t[d][j]]=max(f[t[d][j]],w(a[i],t[d][j]));
			j++;
		}
	}
	while(j<=r){
		f[t[d][j]]=max(f[t[d][j]],w(a[i],t[d][j]));
		j++;
	}
	int cntr=CDQ(mid+1,r,d+1),cnt=l-1;
	i=l;j=mid+1;
	while(i<l+cntl&&j<=mid+cntr){
		if(fabs(x[a[i]]-x[a[j]])<=eps){
			x[a[i]]=min(x[a[i]],x[a[j]]);
			j++;
		}
		else if(x[a[i]]<x[a[j]]){
			while(cnt>l&&getk(s[cnt-1],s[cnt])+eps>getk(s[cnt],a[i]))cnt--;
			s[++cnt]=a[i++];
		}
		else{
			while(cnt>l&&getk(s[cnt-1],s[cnt])+eps>getk(s[cnt],a[j]))cnt--;
			s[++cnt]=a[j++];
		}
	}
	while(i<l+cntl){
		while(cnt>l&&getk(s[cnt-1],s[cnt])+eps>getk(s[cnt],a[i]))cnt--;
		s[++cnt]=a[i++];
	}
	while(j<=mid+cntr){
		while(cnt>l&&getk(s[cnt-1],s[cnt])+eps>getk(s[cnt],a[j]))cnt--;
		s[++cnt]=a[j++];
	}
	copy(s+l,s+r+1,a+l);
	return cnt-l+1;
}
inline long double getk(int i,int j){return (y[i]-y[j])/(x[i]-x[j]);}
inline long double w(int j,int i){return f[j]*(A[i]*R[j]+B[i])/(A[j]*R[j]+B[j]);}