您的位置:首页 > 其它

bzoj 1492: [NOI2007]货币兑换Cash

2016-03-13 06:04 351 查看
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define eps 1e-9
using namespace std;
#define M 100008
double f[M];
struct data
{
double k,a,b,rate,x,y;
int id;
}q[M],t[M];
int zhan[M],n;
bool cmp(data a1,data a2)
{
return a1.k>a2.k;
}
double dp(int a1,int a2)
{
if(!a2)
return -1e20;
if(fabs(q[a1].x-q[a2].x)<eps)
return 1e20;
return (q[a1].y-q[a2].y)/(q[a1].x-q[a2].x);
}
void fen(int l,int r)
{
if(l==r)
{
f[l]=max(f[l],f[l-1]);
q[l].y=f[l]/(q[l].a*q[l].rate+q[l].b);
q[l].x=q[l].rate*q[l].y;
return;
}
int mid=(l+r)>>1,l1=l,l2=mid+1;
for(int i=l;i<=r;i++)
if(q[i].id<=mid)
t[l1++]=q[i];
else
t[l2++]=q[i];
for(int i=l;i<=r;i++)
q[i]=t[i];
fen(l,mid);
int t2=0;
for(int i=l;i<=mid;i++)
{
for(;t2>1&&dp(zhan[t2-1],zhan[t2])<dp(zhan[t2],i)+eps;t2--);
zhan[++t2]=i;
}
t2++;
zhan[t2]=0;
int t1=1;
for(int i=mid+1;i<=r;i++)
{
for(;t1<t2&&dp(zhan[t1],zhan[t1+1])+eps>q[i].k;)
t1++;
f[q[i].id]=max(f[q[i].id],q[zhan[t1]].x*q[i].a+q[zhan[t1]].y*q[i].b);
}
fen(mid+1,r);
l1=l;
l2=mid+1;
for(int i=l;i<=r;i++)
if(((q[l1].x<q[l2].x||(fabs(q[l1].x-q[l2].x)<eps&&q[l1].y<q[l2].y))||l2>r)&&l1<=mid)
t[i]=q[l1++];
else
t[i]=q[l2++];
for(int i=l;i<=r;i++)
q[i]=t[i];
return;
}
int main()
{
scanf("%d%lf",&n,&f[0]);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf",&q[i].a,&q[i].b,&q[i].rate);
q[i].id=i;
q[i].k=-q[i].a/q[i].b;
}
sort(q+1,q+n+1,cmp);
fen(1,n);
printf("%.3lf",f
);
return 0;
}


这是个斜率优化dp,用cdq去做。f[i]代表到i天时的最大获利,q[i].x,q[i].y表示在第i天全部买股票能买多少
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: