Description

最初你有 S 块钱, 有 N 天给你来兑换货币, 求最大获利.

一共只有两种货币 A , B .

对于每一天, 给定 3 个系数 A[i], B[i], Rate[i]

A[i] 表示当天 A 货币的单位价值, B[i] 表示当前 B 货币的单位价值.

第\(i\)天你可以进行以下两种操作: (可以执行多次)

  ① 将 OP% 的 A 货币和 OP% 的 B 货币卖出.

  ② 按照 A : B = Rate[i] 的比例, 用一部分的钱买入货币.

\(n \le 100000\)

Analysis

考虑假如有一天买货币没有用完所有钱更优, 说明这里的前用了后面赚不回来

同理可知: 要么一次性买入货币买光所有钱, 要么一次卖光所有货币

我们将相邻的买卖分为一组

记\(f[i]\)为第\(i\)天(在买之前)最多能有多少钱

于是\(f[i] = \max\{f[i-1], D[j] * A[i] + C[j] * B[i]\}\)

其中\(C[i] = \frac{f[i]}{A[i]*Rate[i] + B[i]}\) 即花光钱能买多少个\(B\)货币

\(D[i] = C[i] * Rate[i]\)即花光钱能买多少个\(A\)货币

这是一个可以斜率优化的式子.

但是注意到\(A,B,C,D\)什么的都并没有单调性

Solution 1

动态维护凸壳

Solution 2

注意到转移只与前面求出来的量有关

那么我们可以进行cdq分治

这样我们就可以排序建凸包, 排序切线询问.

Notice

不是一般序列上的斜率优化, 最好使用\(\det\)

对于切线询问, 除了可以用斜率判, 也可以直接根据答案的单峰性判断, 具体见代码

另外, 凸包比较还是用\(\le ,\ge\)这两个符号好一些

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iostream>
#define rep(i,a,b) for (int i = (a); i <= (b); ++ i)
#define per(i,a,b) for (int i = (a); i >= (b); -- i)
#define For(i,a,b) for (int i = (a); i < (b); ++ i)
using namespace std;
const int M = 1e5 + 7;
typedef double db; inline int ri(){
int x = 0; bool f = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
for (; isdigit(c); c = getchar()) x = x*10+c-48;
return f ? x : -x;
} int n;
db f[M];
db A[M], B[M], C[M], D[M], R[M]; inline db det(db x, db y, db vx, db vy) {return x * vy - y * vx;}
inline bool side(int x, int y, int z) {return det(D[y]-D[x], C[y]-C[x], D[z]-D[x], C[z]-C[x]) >= 0;}
inline db calc(int x, int y) {return D[x] * A[y] + C[x] * B[y];}
inline db V(int x) {return - A[x] / B[x];}
inline bool cmp1(int x, int y) {return D[x] < D[y];}
inline bool cmp2(int x, int y) {return V(x) > V(y);} void cdq(int l, int r){
static int q[M], v[M]; if (l == r) {
f[l] = max(f[l], f[l-1]);
C[l] = f[l] / (A[l] * R[l] + B[l]);
D[l] = C[l] * R[l];
return;
} int mid = l+r >> 1; cdq(l, mid); rep (i, l, mid) q[i] = i;
sort(q+l, q+mid+1, cmp1);
int h = l, t = l-1;
rep (i, l, mid){
while (h < t && side(q[t-1], q[t], q[i]) ) --t;
q[++t] = q[i];
} rep (i, mid+1, r) v[i] = i;
sort(v+mid+1, v+r+1, cmp2);
rep (i, mid+1, r){
int y = v[i];
while (h < t && calc(q[h], y) <= calc(q[h+1], y)) ++h;
f[y] = max(f[y], calc(q[h], y));
} cdq(mid+1, r);
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
#endif scanf("%d%lf", &n, &f[0]); rep (i, 1, n) scanf("%lf%lf%lf", &A[i], &B[i], &R[i]); cdq(1, n); printf("%.3lf\n", f[n]); return 0;
}

BZOJ 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. ●BZOJ 1492 [NOI2007]货币兑换Cash

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

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

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

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

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

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

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

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

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

  7. BZOJ 1492 [NOI2007]货币兑换Cash:斜率优化dp + cdq分治

    传送门 题意 初始时你有 $ s $ 元,接下来有 $ n $ 天. 在第 $ i $ 天,A券的价值为 $ A[i] $ ,B券的价值为 $ B[i] $ . 在第 $ i $ 天,你可以进行两种操 ...

  8. bzoj 1492: [NOI2007]货币兑换Cash【贪心+斜率优化dp+cdq】

    参考:http://www.cnblogs.com/lidaxin/p/5240220.html 虽然splay会方便很多,但是懒得写,于是写了cdq 首先要想到贪心的思路,因为如果在某天买入是能得到 ...

  9. BZOJ 1492 [NOI2007]货币兑换Cash (CDQ分治/splay 维护凸包)

    题目大意:太长了略 splay调了两天一直WA弃疗了 首先,我们可以猜一个贪心,如果买/卖,就一定都买/卖掉,否则不买/卖 反正货币的行情都是已知的,没有任何风险,所以肯定要选择最最最优的方案了 容易 ...

随机推荐

  1. Python__关于列表的引用 以append操作为例

    对于列表这样的可变类型来说,对它操作是不会改变内存地址的. 若列表里面存的元素是整数这样的不可变类型,若修改这个元素那地址还是会改变,如: >>> a = [,,] >> ...

  2. Effective Approaches to Attention-based Neural Machine Translation(Global和Local attention)

    这篇论文主要是提出了Global attention 和 Local attention 这个论文有一个译文,不过我没细看 Effective Approaches to Attention-base ...

  3. 学习python第十四天,模块

    Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块让你能够有逻辑地组织你的 Python 代码段. 把相关的代码 ...

  4. lan口和wan口的配置

    路由器的一排网线接口,分为 lan 和 wan .但不是谁生来就是lan口 或者 wan口 . 也没有谁规定就一个wan口 就只有一个. 网口就是网口, 决定它是 lan口 还是 wan口 ,是由我们 ...

  5. Linux YUM (Yellowdog Updater, Modified) Commands for Package Management

    Linux YUM (Yellowdog Updater, Modified) Commands for Package Management In this article, we will lea ...

  6. 17-比赛1 F - 较小元素 Weak in the Middle (set)

    Seg-El has last chance to make the final changes in order to prevent the destruction of Krypton. He ...

  7. 基于itchat定制聊天机器人

    #coding=utf8import requestsimport itchat #key自己到图灵注册一个 KEY = '************************************** ...

  8. python模块struct和subprocess

    准确地讲,Python没有专门处理字节的数据类型.但由于str既是字符串,又可以表示字节,所以,字节数组=str.而在C语言中,我们可以很方便地用struct.union来处理字节,以及字节和int, ...

  9. 深入理解Angular2变化监测和ngZone

    转载自GitHub JTangming : https://github.com/JTangming/tm/issues/4 Angular应用程序通过组件实例和模板之间进行数据交互,也就是将组件的数 ...

  10. Java从后台重定向(redirect)到另一个项目的方法

    (1)通过ModelAndView跳转 @RequestMapping("alipayforward") public ModelAndView alipayforward(Htt ...