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学习之字符串转换

    配置环境:python 3.6   python编辑器:pycharm 代码如下: #!/usr/bin/env python #-*- coding: utf-8 -*- def strCase() ...

  2. strak组件(10):批量操作

    效果图: 批量删除只是一个例子,可以根据需求定制自己想要的批量操作. 新增函数 def get_action_list(self) 钩子方法,获取要处理的批量操作的函数 def action_mult ...

  3. 14、函数之匿名函数(lambda)

    关键字lambda可以创建匿名函数,语法是:lambda 参数s :表达式.匿名函数与普通函数只有以下几点不同:①没有函数名:②只能有一个表达式:③一定会有返回值,返回值就是该表达式的结果. 另外,匿 ...

  4. python-5模块

    1-使用模块 import sys def test(): args = sys.argv if len(args)==1: print("hello word") elif le ...

  5. cocos2d-x 3.0环境配置(转)

    cocos2d-x 3.0发布有一段时间了,作为一个初学者,我一直觉得cocos2d-x很坑.每个比较大的版本变动,都会有不一样的项目创建方式,每次的跨度都挺大…… 但是凭心而论,3.0RC版本开始 ...

  6. 7 定制10MINs首页2

    1.添加 <div class="ui basic segment"> <h1 class="ui center aligned header" ...

  7. elasticsearch索引和映射

    目录 1. elasticsearch如何实现搜索 1.1 搜索实例 1.2 es中数据的类型 1.3 倒排索引 1.4 分析与分析器 1.4.1 什么是分析器 1.4.2 内置分析器种类 1.4.3 ...

  8. 【Support Vector Regression】林轩田机器学习技法

    上节课讲了Kernel的技巧如何应用到Logistic Regression中.核心是L2 regularized的error形式的linear model是可以应用Kernel技巧的. 这一节,继续 ...

  9. Linux忘记root密码的解决办法

    这里以centos6为例: 第一步:先将系统重新启动,在读秒的时候按下任意键就会出现如下图的菜单界面: 第二步:按下『e』就能够进入grub的编辑模式,如图: 第三步:将光标移动到kernel那一行, ...

  10. selenium初识(二)——之webdriver API

    配置完的环境之后,我们先来写一个小脚本: # __Author__:"Jim_xie" from selenium import webdriver from time impor ...