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. 【php】关于trim,rtrim,ltrim,substr 的字符串切割导致 json,_encode无法 识别数据的问题

    示例 <?php $a = rtrim('南宁 .',' .'); echo $a; //输出 南�� echo json_encode($a); //输出空白 $b = ['name'=> ...

  2. TCP/IP协议之http和https协议

    一.TCP/IP协议 TCP/IP 是不同的通信协议的大集合. 1.TCP - 传输控制协议 TCP 用于从应用程序到网络的数据传输控制. TCP 负责在数据传送之前将它们分割为 IP 包,然后在它们 ...

  3. stdio中牛逼的写法

    用空间换时间的典型 /* * NOTE! This ctype does not handle EOF like the standard C * library is required to. */ ...

  4. 37-生成 JWT Token

    接到上篇文章 安装扩展插件nuget package方法安装包 使用 ctrl+shift+p打开命令面板 增加这个包,  Microsoft.AspNetCore.Authentication.Jw ...

  5. 笔记-mysql-管理及基础操作

    笔记-mysql使用-管理及基础操作 1.      简介 mysql是一个免费的关系型数据库,不过好像被oracle收购了.... 希望它继续免费. 1.1.    相关术语 数据库,表,列,行,冗 ...

  6. 零基础~仿qq登录界面

    html代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...

  7. Matplotlib库介绍

    pyplot的plot()函数 pyplot的中文显示 pyplot的文本显示 pyplot的子绘图区域

  8. Ubuntu 14.10 配置JDK + J2EE

    本文仅作为本人在Ubuntu 14.10下安装JDK + J2EE的一个记录: 安装JDK 从Oracle的官网下载jdk-7u75-linux-x64.tar.gz 将jdk-7u75-linux- ...

  9. 20145202马超 《Java程序设计》第七周学习总结

    Arrays:用于操作数组的工具类. 里面都是静态方法. asList:将数组变成list集合. 把数组变成集合的好处:可以使用集合的思想来操作数组中的元素. 将数组变成集合的时候不可以使用集合的增删 ...

  10. Spring---配置文件概述

    概述 Spring 的配置文件是用于指导 Spring 工厂进行Bean的生产.依赖关系注入及 Bean 实例分发的“图纸”,它是一个或多个标准的XML文档,J2EE 程序员必须学会并灵活应用这份“图 ...