Description

小Y最近在一家金券交易所工作。该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下
简称B券)。每个持有金券的顾客都有一个自己的帐户。金券的数目可以是一个实数。每天随着市场的起伏波动,
两种金券都有自己当时的价值,即每一单位金券当天可以兑换的人民币数目。我们记录第 K 天中 A券 和 B券 的
价值分别为 AK 和 BK(元/单位金券)。为了方便顾客,金券交易所提供了一种非常方便的交易方式:比例交易法
。比例交易法分为两个方面:(a)卖出金券:顾客提供一个 [0,100] 内的实数 OP 作为卖出比例,其意义为:将
 OP% 的 A券和 OP% 的 B券 以当时的价值兑换为人民币;(b)买入金券:顾客支付 IP 元人民币,交易所将会兑
换给用户总价值为 IP 的金券,并且,满足提供给顾客的A券和B券的比例在第 K 天恰好为 RateK;例如,假定接
下来 3 天内的 Ak、Bk、RateK 的变化分别为:
假定在第一天时,用户手中有 100元 人民币但是没有任何金券。用户可以执行以下的操作:
注意到,同一天内可以进行多次操作。小Y是一个很有经济头脑的员工,通过较长时间的运作和行情测算,他已经
知道了未来N天内的A券和B券的价值以及Rate。他还希望能够计算出来,如果开始时拥有S元钱,那么N天后最多能
够获得多少元钱。

Input

输入第一行两个正整数N、S,分别表示小Y能预知的天数以及初始时拥有的钱数。接下来N行,第K行三个实数AK、B
K、RateK,意义如题目中所述。对于100%的测试数据,满足:0<AK≤10;0<BK≤10;0<RateK≤100;MaxProfit≤1
0^9。
【提示】
1.输入文件可能很大,请采用快速的读入方式。
2.必然存在一种最优的买卖方案满足:
每次买进操作使用完所有的人民币;
每次卖出操作卖出所有的金券。
 

Output

只有一个实数MaxProfit,表示第N天的操作结束时能够获得的最大的金钱数目。答案保留3位小数。

Sample Input

3 100
1 1 1
1 2 2
2 2 3

Sample Output

225.000
 
 
CDQ分治或Spaly动态维护凸包
 
 
首先是CDQ分治版本
#include<cstdio>
#include<algorithm>
#define MN 100001
using namespace std; int read_p,read_ca;
inline int read(){
read_p=;read_ca=getchar();
while(read_ca<''||read_ca>'') read_ca=getchar();
while(read_ca>=''&&read_ca<='') read_p=read_p*+read_ca-,read_ca=getchar();
return read_p;
}
struct na{
double A,B,R,q;
int id;
}b[MN],x[MN];
struct ma{
double A,B;
}q[MN],px[MN];
bool cmp(na a,na b){
return a.q>b.q;
}
bool operator < (ma a,ma b){
if (a.A==b.A) return a.B<b.B;else return a.A<b.A;
}
int n,top,s[MN];
double f[MN];
inline double max(double a,double b){return a>b?a:b;}
inline double fk(ma a,ma b){
if (a.A==b.A) return 2e9*(a.B<=b.B?:-);
return (a.B-b.B)/(a.A-b.A);
}
inline void work(int l,int r){
int i;
if (l==r){
f[l]=max(f[l],f[l-]);
q[l].A=f[l]/(b[l].R*b[l].A+b[l].B)*b[l].R;
q[l].B=f[l]/(b[l].R*b[l].A+b[l].B);
return;
}
int mid=(l+r)>>,l1=l,l2=mid+;
for (i=l;i<=r;i++) if (b[i].id<=mid) x[l1++]=b[i];else x[l2++]=b[i];
for (i=l;i<=r;i++) b[i]=x[i];
work(l,mid);top=; for (i=l;i<=mid;s[++top]=i++)
while(top>) if (fk(q[s[top-]],q[s[top]])<fk(q[s[top]],q[i])) s[top--]=;else break; for (i=mid+;i<=r;f[b[i].id]=max(f[b[i].id],q[s[top]].A*b[i].A+q[s[top]].B*b[i].B),i++)
while(top>) if (fk(q[s[top-]],q[s[top]])<-b[i].q) s[top--]=;else break; work(mid+,r);
l1=l;l2=mid+;
for (int i=l;i<=r;i++)
if (((q[l1]<q[l2])||(l2>r))&&l1<=mid)
px[i]=q[l1++];else px[i]=q[l2++];
for (int i=l;i<=r;i++)
q[i]=px[i];
}
int main(){
int i;
n=read();scanf("%lf",&f[]);
for (i=;i<=n;i++) scanf("%lf%lf%lf",&b[i].A,&b[i].B,&b[i].R),b[i].q=b[i].A/b[i].B,b[i].id=i;
sort(b+,b++n,cmp);
work(,n);
printf("%.3lf\n",f[n]);
}

CDQ

 

然后平衡树

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define MN 100001
using namespace std; int n,ne[MN],fi[MN],p;
double X[MN],Y[MN],f[MN],A[MN],B[MN],R[MN],q[MN];
inline double fk(int a,int b){
if (!a) return 2e9;if (!b) return -2e9;
if (X[a]==X[b]) return 2e9*(Y[a]<=Y[b]?:-);
return (Y[a]-Y[b])/(X[a]-X[b]);
}
struct tree{
int l,r,k,w,f,s;
tree(){
f=l=r=;
}
};
inline double max(double a,double b){return a>b?a:b;}
struct splay_tree{
int size,root;
tree t[];
splay_tree(){
size=;root=;
}
inline void ler(int &p){
int k=t[p].r;
t[k].f=t[p].f;
t[p].f=k;
t[t[k].l].f=p;
t[p].r=t[k].l;
t[k].l=p;
t[k].s=t[p].s;
t[p].s=t[t[p].l].s+t[t[p].r].s+t[p].w;
p=k;
}
inline void rir(int &p){
int k=t[p].l;
t[k].f=t[p].f;
t[p].f=k;
t[t[k].r].f=p;
t[p].l=t[k].r;
t[k].r=p;
t[k].s=t[p].s;
t[p].s=t[t[p].l].s+t[t[p].r].s+t[p].w;
p=k;
}
inline void ph(int &x,bool bo){if (bo) rir(x);else ler(x);}
inline bool gc(int x){return t[t[x].f].l==x;}
inline void rot(int p){
if (t[p].f==root) ph(root,gc(p));else
if (gc(t[p].f)) ph(t[t[t[p].f].f].l,gc(p));else ph(t[t[t[p].f].f].r,gc(p));
}
inline void splay(int p,int f){
while(t[p].f!=f){
if (t[t[p].f].f==f) rot(p);else
if (gc(t[p].f)==gc(p)) rot(t[p].f),rot(p);else rot(p),rot(p);
}
}
inline void insert(int &p,int k,int f){
if (!p){
p=++size;
t[p].k=k;
t[p].w=;
t[p].f=f;
t[p].s=;
splay(p,);
return;
}
t[p].s++;
if (X[t[p].k]>X[k]) insert(t[p].l,k,p);else insert(t[p].r,k,p);
}
inline int qui(int p,int k){
if (!p) return -;
if (X[t[p].k]>X[k]) return qui(t[p].l,k);else{
int u=qui(t[p].r,k);
if (u==-) splay(p,),u=p;return u;
}
}
inline int ask(int p,double k){
if (!p) return -;
if (fk(p,ne[p])==k) return p;else
if (fk(p,ne[p])>k) return ask(t[p].r,k);else
if (t[p].l==) return p;else{
int u=ask(t[p].l,k);
if (u==-){splay(p,);return p;}else return u;
}
}
};
splay_tree t;
inline void in(int x){
int s=t.qui(t.root,x),p=ne[s];
if (s&&X[s]==X[x]) if (Y[s]>=Y[x]){t.size++;return;}else s=fi[s];
if (fk(s,x)<fk(x,p)){t.size++;return;}
if (s==-){
p=ne[];
while ((fk(x,p)<fk(p,ne[p]))&&p) p=ne[p];
t.splay(p,);t.t[p].l=;
ne[x]=p;
ne[]=x;
fi[x]=;
fi[ne[x]]=x;
t.insert(t.root,x,);
return;
}
while (fk(fi[s],s)<fk(s,x)&&s) s=fi[s];
while ((fk(x,p)<fk(p,ne[p]))&&p) p=ne[p];
if ((!s)&&(!p)) t.root=;else
if ((!s)&&p) t.splay(p,),t.t[p].l=;else
if (s&&(!p)) t.splay(s,),t.t[s].r=;else
t.splay(s,),t.splay(p,s),t.t[p].l=;
ne[s]=x;fi[x]=s;
ne[x]=p;fi[p]=x;
t.insert(t.root,x,);
}
inline int que(double k){
return t.ask(t.root,k);
}
int main(){
scanf("%d%lf",&n,&f[]);
for (int i=;i<=n;i++) scanf("%lf%lf%lf",&A[i],&B[i],&R[i]),q[i]=-A[i]/B[i];
X[]=f[]/(R[]*A[]+B[])*R[];
Y[]=f[]/(R[]*A[]+B[]);
in();
for (int i=;i<=n;i++){
p=que(q[i]);
f[i]=max(X[p]*A[i]+Y[p]*B[i],f[i-]);
X[i]=f[i]/(A[i]*R[i]+B[i])*R[i];
Y[i]=f[i]/(R[i]*A[i]+B[i]);
in(i);
}
printf("%.3lf\n",f[n]);
return ;
}

Spaly

1492: [NOI2007]货币兑换Cash的更多相关文章

  1. BZOJ 1492: [NOI2007]货币兑换Cash( dp + 平衡树 )

    dp(i) = max(dp(i-1), x[j]*a[i]+y[j]*b[i]), 0<j<i. x, y表示某天拥有的最多钱去买金券, 金券a和金券b的数量. 然后就很明显了...平衡 ...

  2. 1492: [NOI2007]货币兑换Cash【CDQ分治】

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 4166  Solved: 1736[Submit][Sta ...

  3. ●BZOJ 1492 [NOI2007]货币兑换Cash

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1492 题解: 斜率优化DP,CDQ分治 定义$DP[i]$为第i天结束后的最大收益. 由于题 ...

  4. 【BZOJ】1492: [NOI2007]货币兑换Cash(cdq分治)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 蒟蒻来学学cdq神算法啊.. 详见论文 陈丹琦<从<Cash>谈一类分治算法 ...

  5. bzoj 1492 [NOI2007]货币兑换Cash(斜率dp+cdq分治)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1492   [题意] 有AB两种货币,每天可以可以付IPi元,买到A券和B券,且A:B= ...

  6. 斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash

    Description Input 第一行两个正整数N.S,分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来N 行,第K 行三个实数AK.BK.RateK,意义如题目中所述 Output 只有 ...

  7. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  8. bzoj 1492: [NOI2007]货币兑换Cash

    Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...

  9. 【BZOJ】1492: [NOI2007]货币兑换Cash

    [题意]初始资金s,有两种金券A和B,第i天,买入时将投入的资金购买比例为rate[i]的两种股票,卖出时将持有的一定比例的两种股票卖出,第i天股票价格为A[i],B[i],求最大获利.n<=1 ...

随机推荐

  1. 安装卸载selenium

    安装: C:\Users\xiongjiawei>pip install selenium==2.48.0 Collecting selenium==2.48.0 Retrying (Retry ...

  2. 在 ReactNative 的 App 中,集成 Bugly 你会遇到的一些坑

    一.前言 最近开新项目,准备尝试一下 ReactNative,所以前期做了一些调研工作,ReactNative 的优点非常的明显,可以做到跨平台,除了少部分 UI 效果可能需要对不同的平台进行单独适配 ...

  3. The Movie db (TMDB)的API申请

    在共享API TMDB中申请时,一只报错Application summary please elaborate on how you plan to use our API,我是用汉字描述的,开始以 ...

  4. VR\AR 使用 SceneKit

    VR\AR 使用 SceneKit http://www.jianshu.com/c/70d63e3941fd

  5. http中的get和post(一)

    GET和POST有什么区别?及为什么网上的多数答案都是错的. 如果有人问你,GET和POST,有什么区别?你会如何回答? 我的经历 前几天有人问我这个问题.我说GET是用于获取数据的,POST,一般用 ...

  6. bzoj 1150: [CTSC2007]数据备份Backup

    Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家 ...

  7. springMVC(5)---导入excel文件数据到数据库

    springMVC(5)---导入excel文件数据到数据库 上一篇文章写了从数据库导出数据到excel文件,这篇文章悄悄相反,写的是导入excel文件数据到数据库.上一篇链接:springMVC(4 ...

  8. 本地Git仓库同步到Bitbucket 远程Git仓库

    转载自:http://blog.csdn.net/lue2009/article/details/46553829 本地仓库内容可以和多个远程仓库同步,本地仓库出问题或者远程仓库其中一个有问题,那么剩 ...

  9. 微信小程序开发之模板消息

    一.添加模板 登录https://mp.weixin.qq.com获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用,详见模板审核说明 页面的 <form/> 组件,属性r ...

  10. eclipse启动tomcat不能访问解决

    tomcat在eclipse里面能正常启动,而在浏览器中访问http://localhost:8080/不能访问,且报404错误.同时其他项目页面也不能访问. 关闭eclipse里面的tomcat,在 ...