http://www.lydsy.com/JudgeOnline/problem.php?id=1492 (题目链接)

题意

  两种金券,金券按照比例交易:买入时,将投入的资金购买比例为$rate[i]$的两种金券;卖出时,卖出持有一定比例的金券。已知未来$n$天金券的价格$A[i],B[i]$,初始资金为$S$,求最大获利。

Solution

  首先根据贪心的思想,每次买入和卖出一定是花光了所有的资金和卖掉了所有的金券。$f[i]$表示第$i$天的最大获利,那么转移分两种情况,在这天卖出和不在这一天卖出,在一天卖出我们枚举上一次在哪一天买入金券:

\begin{aligned}  f[i]=MAX\{MAX\{\frac{f[j]}{rate[j]*A[j]+B[j]}*rate[j]*A[i]+\frac{f[j]}{rate[j]*A[j]+B[j]}*B[i]\},f[i-1]\}   \end{aligned}

  这很显然是个斜率的式子:

\begin{aligned}  X[j]&=\frac{f[j]*rate[j]}{rate[j]*A[j]+B[j]}  \\  Y[j]&=\frac{f[j]}{rate[j]*A[j]+B[j]}   \end{aligned}

  但是横坐标和斜率都不单调,所以我们使用CDQ分治。每次先处理$[l,mid]$位置的$f$,然后再用这些$f$构凸包去更新$[mid+1,r]$位置的$f$。

  代码膜PoPoQQQ

细节

  横坐标相等

代码

// bzoj1492
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<30)
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=100010;
double f[maxn];
int n,st[maxn];
struct data {double A,B,rate,k;int pos;}q[maxn],nq[maxn];
struct point {double x,y;}p[maxn],np[maxn]; bool cmp(data a,data b) {return a.k<b.k;}
double slope(point a,point b) {
return a.x==b.x ? inf*(a.y>b.y ? 1 : -1) : (a.y-b.y)/(a.x-b.x);
}
void solve(int l,int r) {
if (l==r) {
f[l]=max(f[l],f[l-1]);
p[l].x=f[l]/(q[l].A+q[l].B/q[l].rate);
p[l].y=f[l]/(q[l].A*q[l].rate+q[l].B);
return;
}
int mid=(l+r)>>1,l1=l,l2=mid+1,top=0;
for (int i=l;i<=r;i++) q[i].pos<=mid ? nq[l1++]=q[i] : nq[l2++]=q[i];
for (int i=l;i<=r;i++) q[i]=nq[i];
solve(l,mid);
for (int i=l;i<=mid;i++) {
while (top>1 && slope(p[st[top-1]],p[st[top]])<slope(p[st[top]],p[i])) top--;
st[++top]=i;
}
for (int i=mid+1;i<=r;i++) {
while (top>1 && slope(p[st[top-1]],p[st[top]])<q[i].k) top--;
f[q[i].pos]=max(f[q[i].pos],q[i].A*p[st[top]].x+q[i].B*p[st[top]].y);
}
solve(mid+1,r);
for (int i=l,j=mid+1,k=l;i<=mid || j<=r;) {
if (j>r || (i<=mid && p[i].x<p[j].x)) np[k++]=p[i++];
else np[k++]=p[j++];
}
for (int i=l;i<=r;i++) p[i]=np[i];
}
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].k=-q[i].A/q[i].B;
q[i].pos=i;
}
sort(q+1,q+1+n,cmp);//先按照斜率排序常数会小很多
solve(1,n);
printf("%.3lf",f[n]);
return 0;
}

【bzoj1492】 NOI2007—货币兑换Cash的更多相关文章

  1. [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化)

    [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化) 题面 分析 dp方程推导 显然,必然存在一种最优的买卖方案满足:每次买进操作使用完所有的人民币:每次卖出操作卖出所有 ...

  2. [BZOJ1492][NOI2007]货币兑换Cash(斜率优化+CDQ分治)

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

  3. bzoj1492[NOI2007]货币兑换Cash cdq分治+斜率优化dp

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

  4. bzoj千题计划237:bzoj1492: [NOI2007]货币兑换Cash

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 dp[i] 表示 第i天卖完的最大收益 朴素的dp: 枚举从哪一天买来的在第i天卖掉,或者是不 ...

  5. BZOJ1492: [NOI2007]货币兑换Cash 【dp + CDQ分治】

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 5391  Solved: 2181 [Submit][S ...

  6. [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包

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

  7. BZOJ1492: [NOI2007]货币兑换Cash

    设$x_j$,$y_j$为第$j$天能买的A,B券数量,$f_i$为第$i$天的最大收益.$f_i=\max_{1\le j<i}a_ix_j+b_iy_j$,最大化$f_i$即找一个点$(x_ ...

  8. Bzoj1492: [NOI2007]货币兑换Cash(不单调的斜率优化)

    题面 传送门 Sol 题目都说了 必然存在一种最优的买卖方案满足: 每次买进操作使用完所有的人民币: 每次卖出操作卖出所有的金券. 设\(f[i]\)表示第\(i\)天可以有的最大钱数 枚举\(j&l ...

  9. bzoj1492 [NOI2007]货币兑换Cash【cdq分治】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1492 推荐博客:http://www.cnblogs.com/zig-zag/archive ...

  10. cdq分治入门--BZOJ1492: [NOI2007]货币兑换Cash

    n<=100000天,一开始有s块钱,每天股票A价格ai,B价格bi,每天可以做的事情:卖出股票:按A:B=RTi的比例买入股票.问最后的最大收益.股票可以为浮点数,答案保留三位. 用脚指头想想 ...

随机推荐

  1. 算法篇(前序)——Java的集合

    菜鸟拙见,望请纠正:附上JDK参考文档(中文文档和英文文档):链接:https://pan.baidu.com/s/14KDmCtQxeGCViq7e0zENjA 密码:e9xs  以及算法篇全文链接 ...

  2. 大数据入门第十二天——azkaban入门

    一.概述 1.azkaban是什么 通过官方文档:https://azkaban.github.io/ Azkaban is a batch workflow job scheduler create ...

  3. 1、JVM 内存模型+运行时数据区+JVM参数

    JMM(内存模型)  1.’主内存+每个线程有自己的内存 JVM运行时数据区 包含:1.程序计算器(每个线程自带):2.JAVA-STACK(每个线程自带):3.本地方法stack:4.堆:5.方法区 ...

  4. HNOI2019 摸鱼记

    感觉准备省选时有点浮躁,没有准备联赛时那样认真, 希望能将这次省选当做一个教训吧QAQ. Day -inf 基本上把要学的东西都学了,至少做到了自己心里有底. Day 0 乒乓球室没开差评,打隔膜不带 ...

  5. ajax传递数组给controller的实现方法和坑

    这里是前端向后端传递一个数组的方式,参考下面这个示例: (主要是将前端的数组,用 JSON.stringify() 方法json化一下,然后后端springmvc接收到以后,使用 JSONArray  ...

  6. 微信小程序之授权 wx.authorize

    一. wx.authorize(Object object) 提前向用户发起授权请求.调用后会立刻弹窗询问用户是否同意授权小程序使用某项功能或获取用户的某些数据,但不会实际调用对应接口.如果用户之前已 ...

  7. Security3: 架构和权限

    架构(Schema)是数据库对象(比如,Table,View,存储过程等)的容器,授予用户对Schema访问的权限,就是授予用户对Schema下所有object的访问权限. 一,架构(Schema)是 ...

  8. Visual studio 2017中 Javascript对于Xrm对象模型没有智能提示的解决办法

    Visual studio 2017中 Javascript对于Xrm对象模型没有智能提示的解决办法 先上个图.语法提示支持到 Microsoft Dynamics xRM API 8.2 也就是cr ...

  9. 504. Base 7

    Given an integer, return its base 7 string representation. Example 1: Input: 100 Output: "202&q ...

  10. zookeeper应用

    1. 下载zookeeper-3.4.10.tar.gz 2.tar zxvf zoo*.tar.gz 3. cd /usr/local/zookeeper/zookeeper-3.4.10/conf ...