[BZOJ1492][NOI2007]货币兑换Cash(斜率优化+CDQ分治)
1492: [NOI2007]货币兑换Cash
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 5838 Solved: 2345
[Submit][Status][Discuss]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、BK、RateK,意义如题目中所述。对于100%的测试数据,满足:0<AK≤10;0<BK≤10;0<RateK≤100;MaxProfit≤10^9。【提示】1.输入文件可能很大,请采用快速的读入方式。2.必然存在一种最优的买卖方案满足:每次买进操作使用完所有的人民币;每次卖出操作卖出所有的金券。Output
只有一个实数MaxProfit,表示第N天的操作结束时能够获得的最大的金钱数目。答案保留3位小数。
Sample Input
3 100
1 1 1
1 2 2
2 2 3Sample Output
225.000HINT
Source
列出转移方程,化成斜率的式子就可以用斜率优化了,但是这题的横坐标询问不单调所以要用平衡树维护凸壳,而平衡树的替代品就是CDQ分治。
这里我们同时也可以看出,这是个三维偏序,$x_i$和$w_i$各占一维。注意$l=r$的时候dp[l]=dp[l-1]!!!
设我们化成的形式为$\frac{y_k-y_j}{x_k-x_j} \geqslant w_i$,那么:
当$w_i$不满足单调性时可以用二分。
当$x_i$不满足单调性时用CDQ分治或平衡树。
当均满足单调性时直接用单调栈即可。
#include<cmath>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=;
double eps=1e-;
struct P{ double a,b,x,y,k,r; int id; }p[N],q[N];
int n,h[N]; double dp[N];
bool cmp(P a,P b){ return a.k>b.k; } double getk(int u,int v){
if (!v) return -1e20;
if (fabs(p[u].x-p[v].x)<eps) return 1e20;
return (p[u].y-p[v].y)/(p[u].x-p[v].x);
} void solve(int l,int r){
if (l==r){
dp[l]=max(dp[l],dp[l-]);
p[l].y=dp[l]/(p[l].a*p[l].r+p[l].b); p[l].x=p[l].y*p[l].r;
return;
}
int mid=(l+r)>>,j=l,k=mid+;
rep(i,l,r) if (p[i].id<=mid) q[j++]=p[i]; else q[k++]=p[i];
rep(i,l,r) p[i]=q[i];
solve(l,mid); int ed=,st=;
rep(i,l,mid){
while (ed> && getk(h[ed],i)+eps>getk(h[ed-],h[ed])) ed--;
h[++ed]=i;
}
rep(i,mid+,r){
while (st<ed && getk(h[st],h[st+])+eps>p[i].k) st++;
dp[p[i].id]=max(dp[p[i].id],p[h[st]].x*p[i].a+p[h[st]].y*p[i].b);
}
solve(mid+,r); j=l; k=mid+;
rep(i,l,r)
if (j<=mid && (p[j].x<p[k].x || (fabs(p[j].x-p[k].x)<eps && p[j].y<p[k].y) || k>r)) q[i]=p[j++];
else q[i]=p[k++];
rep(i,l,r) p[i]=q[i];
} int main(){
freopen("bzoj1492.in","r",stdin);
freopen("bzoj1492.out","w",stdout);
scanf("%d%lf",&n,&dp[]);
rep(i,,n){
scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].r);
p[i].k=-p[i].a/p[i].b; p[i].id=i;
}
sort(p+,p+n+,cmp); solve(,n); printf("%.3f\n",dp[n]);
return ;
}
[BZOJ1492][NOI2007]货币兑换Cash(斜率优化+CDQ分治)的更多相关文章
- 【BZOJ1492】[NOI2007]货币兑换Cash 斜率优化+cdq分治
[BZOJ10492][NOI2007]货币兑换Cash Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下简称B券).每 ...
- [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 5907 Solved: 2377[Submit][Sta ...
- BZOJ1492: [NOI2007]货币兑换Cash 【dp + CDQ分治】
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MB Submit: 5391 Solved: 2181 [Submit][S ...
- BZOJ.1492.[NOI2007]货币兑换(DP 斜率优化 CDQ分治/Splay)
BZOJ 洛谷 如果某天能够赚钱,那么一定会在这天把手上的金券全卖掉.同样如果某天要买,一定会把所有钱花光. 那么令\(f_i\)表示到第\(i\)天所拥有的最多钱数(此时手上没有任何金券),可以选择 ...
- 【BZOJ 1492】 [NOI2007]货币兑换Cash 斜率优化DP
先说一下斜率优化:这是一种经典的dp优化,是OI中利用数形结合的思想解决问题的典范,通常用于优化dp,有时候其他的一些决策优化也会用到,看待他的角度一般有两种,但均将决策看为二维坐标系上的点,并转化为 ...
- 洛谷P4027 [NOI2007]货币兑换(dp 斜率优化 cdq 二分)
题意 题目链接 Sol 解题的关键是看到题目里的提示... 设\(f[i]\)表示到第\(i\)天所持有软妹币的最大数量,显然答案为\(max_{i = 1}^n f[i]\) 转移为\(f_i = ...
- BZOJ 1492: [NOI2007]货币兑换Cash 斜率优化 + splay动态维护凸包
Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
- [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化)
[BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化) 题面 分析 dp方程推导 显然,必然存在一种最优的买卖方案满足:每次买进操作使用完所有的人民币:每次卖出操作卖出所有 ...
- BZOJ_3963_[WF2011]MachineWorks_斜率优化+CDQ分治
BZOJ_3963_[WF2011]MachineWorks_斜率优化+CDQ分治 Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM) ...
随机推荐
- 使用OpenCV和Python进行人脸识别
介绍 人脸识别是什么?或识别是什么?当你看到一个苹果时,你的大脑会立刻告诉你这是一个苹果.在这个过程中,你的大脑告诉你这是一个苹果水果,用简单的语言来说就是识别.那么什么是人脸识别呢?我肯定你猜对了. ...
- supervisor之启动rabbitmq报错原因
前言 今天重启了服务器,发现supervisor管理的rabbitmq的进程居然启动失败了,查看日志发现老是报错,记录一下解决的办法. 报错:erlexec:HOME must be set 找了网上 ...
- 【swupdate文档 三】SWUpdate: 嵌入式系统的软件升级
SWUpdate: 嵌入式系统的软件升级 概述 本项目被认为有助于从存储媒体或网络更新嵌入式系统.但是,它应该主要作为一个框架来考虑,在这个框架中可以方便地向应用程序添加更多的协议或安装程序(在SWU ...
- makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解【转】
转自:http://www.cnblogs.com/lifexy/p/7065175.html 在linux中输入vi Makefile 来实现创建Makefile文件 注意:命令行前必须加TAB键 ...
- Linux内核中的队列 kfifo【转】
转自:http://airekans.github.io/c/2015/10/12/linux-kernel-data-structure-kfifo#api 在内核中经常会有需要用到队列来传递数据的 ...
- spring中的任务调度Quartz
Spring 整合 Quartz 任务调度 主要有两种方式. Quartz的官网:http://www.quartz-scheduler.org/ 这两种只是一些配置文件简单配置就OK了,但是根本无法 ...
- u-boot中的Makefile
在windos下,pc机上电之后,BIOS会初始化硬件配置,为内核传递参数,引导操作系统启动,并且识别C盘.D盘.等整个操作系统启动起来之后,才可以运行应用程序比如QQ.QQ音影.同理,在嵌入式Lin ...
- git - git命令中文显示乱码
使用git add添加要提交的文件的时候,如果文件名是中文,会显示形如897\232\350\256...的乱码,解决办法: git config --global core.quotepath ...
- centos修改oracle字符集
1.首先以sysdba的身份登录上去 conn /as sysdba2.关闭数据库shutdown immediate;3.以mount打来数据库,startup mount4.设置session S ...
- qt调用仪器驱动库dll实现程控
在<使用qt+visa实现程控>中实现了qt调用visa库的简单Demo本文将尝试使用qt调用仪器驱动库来实现对仪器仪表的程控 开发环境 系统: windows 10 环境: qt 5.8 ...


