记录编号 |
360550 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[NOI 2007]货币兑换 |
最终得分 |
100 |
用户昵称 |
FoolMike |
是否通过 |
通过 |
代码语言 |
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;
}