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. 20155327 EXP8 Web基础

    20155320 EXP8 Web基础 基础问题回答 什么是表单? 表单:可以收集用户的信息和反馈意见,是网站管理者与浏览者之间沟通的桥梁. 表单由文本域.复选框.单选框.菜单.文件地址域.按钮等表单 ...

  2. Luogu T24242 购物券Ⅰ(数据已加强)

    这是一道比赛时的题目,但由于我没报名,所以浪费了一个大好的切水题的机会. 是经典的meet in middle(折半搜索)的模板题,但是之前一直没找到这种题目,今天终于看到了. 由于m的范围极大,因此 ...

  3. P2463 [SDOI2008]Sandy的卡片

    写一种\(O(nm)\)的做法,也就是\(O(\sum 串长)\)的. 先通过差分转化,把每个数变成这个数与上一个数的差,第一个数去掉,答案就是最长公共子串+1 按照套路把所有串拼起来,中间加一个分隔 ...

  4. [BZOJ4722]由乃[鸽巢原理+bitset+倍增]

    题意 给定长为 \(n\) 序列 \(a\) ,要求支持两种操作: \(1.\) 询问在一个区间 \([l,r]\) 中,是否能够选出两个交集为空的集合 $ \rm X ,Y$, 使得 \(\sum_ ...

  5. 手撸orm

    ORM简介 ORM即Object Relational Mapping,全称对象关系映射.当我们需要对数据库进行操作时,势必需要通过连接数据.调用sql语句.执行sql语句等操作,ORM将数据库中的表 ...

  6. Asp.Net_Session跟Cookie的记住登陆名

    最近在做ASP.NET的项目时,接触到了登陆权限模块,所有总结了一下登陆时用到的知识和方法技巧. 如图说明:实现的效果如图,由于验证码验证比较简单这里就不介绍了 首先用代码生成器生成项目,以三层为例进 ...

  7. Mvc4_@Styles.Render提高性能

    在页面上可以用@Styles.Render("~/Content/css") 来加载css 首先要在App_Start 里面BundleConfig.cs 文件里面 添加要包含的c ...

  8. Unity 角色场景传送功能

    传送触发器 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine. ...

  9. Unity攻击敌人时产生泛白效果

    Shader的代码如下,主要是将透明度为1的像素点输出为白色,其中_BeAttack表示角色被攻击的泛白状态 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_M ...

  10. 软件工程 BUAAMOOC项目Postmortem结果

    设想和目标 1.我们的软件要解决什么问题?是否定义的很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件是基于北航MOOC网站做的Android手机客户端,用于便捷的在学校里通过手机做到随时随地 ...