Description

题库链接

(按我的语文水平完全无 fa♂ 概括题意,找了 hahalidaxin 的题意简述...

有 \(AB\) 两种货币,每天可以可以付 \(IP_i\) 元,买到 \(A\) 券和 \(B\) 券,且 \(A:B=Rate_i\) ,也可以卖掉 \(OP_i\%\) 的 \(A\) 券和 \(B\) 券,每天 \(AB\) 价值为 \(A_i\) 和 \(B_i\) 。
开始有 \(S\) 元, \(n\) 天后手中不能有 \(AB\) 券,给出 \(A_i,B_i,Rate_i\) ,问最大获益。

\(1\leq n\leq 100000\)

Solution

首先基于一个贪心思想:必然存在一种最优的买卖方案满足:每次买进操作使用完所有的人民币;每次卖出操作卖出所有的金券。

所以说其实对于每一天,其能够获得的最多的 \(A,B\) 券个数是已知的,假设第 \(i\) 天获得的最多的 \(A\) 券为 \(f\) , \(i\) 天之前能够得到最多的钱为 \(s\) 。那么有 \[fA_i+\frac{fB_i}{rate_i}=s\Rightarrow f=\frac{rate_is}{rate_iA_i+B_i}\]

那么容易得到 \(O(n^2)\) 的 \(DP\) 。可以获得 \(60pts\) 。

考虑优化。还是由刚才的思想。

我们不妨记 \(f_i\) 表示第 \(i\) 天最大的收益。 注意,此处 \(DP\) 数组的含义发生了变化 。

记第 \(i\) 天得到的最多的 \(A\) 券为 \(x_i\) , \(B\) 券为 \(y_i\) 。显然 \(x_i=rate_iy_i\) ,有 \[f_i=\max_{0\leq j<i} A_ix_j+B_iy_j\]

将上述式子变为斜距式: \[y=-\frac{A_i}{B_i}x+\frac{f_i}{B_i}\]

显然只要截距越大, \(f_i\) 越大。

现在对于每个 \(i\) 前的每天都可以抽象成一个点对 \((x,y)\) 。显然只要使第 \(i\) 天的“这条直线”切于前面 \(0\sim i-1\) 天的点对组成的上凸包时即可得到 \({f_i}_{max}\) 。

用 \(CDQ\) 维护即可。

Code

60pts

//It is made by Awson on 2018.3.20
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, s;
double f[N+5], a[N+5], b[N+5], rate[N+5], ans; void work() {
read(n), read(s);
for (int i = 1; i <= n; i++) scanf("%lf%lf%lf", &a[i], &b[i], &rate[i]);
ans = s;
for (int i = 1; i <= n; i++) {
for (int j = 1; j < i; j++)
ans = max(ans, f[j]*a[i]+f[j]/rate[j]*b[i]);
f[i] = ans*rate[i]/(a[i]*rate[i]+b[i]);
}
printf("%.3lf\n", ans);
}
int main() {work(); return 0; }

100pts

//It is made by Awson on 2018.3.21
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000;
const double eps = 1e-7, INF = 2e33;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, s, S[N+5], top;
struct tt {double x, y, k; int id; }ob[N+5];
double f[N+5], a[N+5], b[N+5], rate[N+5];
bool compk(const tt &a, const tt &b) {return a.k > b.k; }
bool compid(const tt &a, const tt &b) {return a.id < b.id; }
bool comppos(const tt &a, const tt &b) {return a.x == b.x ? a.y < b.y : a.x < b.x; } double k(const int &a, const int &b) {
if (ob[a].x-ob[b].x < eps) return -INF;
return (ob[a].y-ob[b].y)/(ob[a].x-ob[b].x);
}
void solve(int l, int r) {
if (l == r) {
f[l] = max(f[l], f[l-1]);
ob[l].y = f[l]/(a[l]*rate[l]+b[l]);
ob[l].x = rate[l]*ob[l].y;
return;
}
int mid = (l+r)>>1;
sort(ob+l, ob+r+1, compid); solve(l, mid); top = 0;
for (int i = l; i <= mid; i++) {
while (top >= 2 && k(i, S[top]) > k(S[top], S[top-1])) --top;
S[++top] = i;
}
sort(ob+mid+1, ob+r+1, compk); int loc = 1;
for (int i = mid+1; i <= r; i++) {
while (loc < top && ob[i].k < k(S[loc+1], S[loc])) ++loc;
f[ob[i].id] = max(f[ob[i].id], a[ob[i].id]*ob[S[loc]].x+b[ob[i].id]*ob[S[loc]].y);
}
solve(mid+1, r); sort(ob+l, ob+r+1, comppos);
}
void work() {
read(n), read(s); f[0] = s;
for (int i = 1; i <= n; i++) {
scanf("%lf%lf%lf", &a[i], &b[i], &rate[i]);
ob[i].id = i, ob[i].k = -a[i]/b[i];
}
solve(1, n); printf("%.3lf\n", f[n]);
}
int main() {work(); return 0; }

[NOI 2007]货币兑换Cash的更多相关文章

  1. NOI 2007 货币兑换Cash (bzoj 1492) - 斜率优化 - 动态规划 - CDQ分治

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

  2. 【BZOJ-1492】货币兑换Cash DP + 斜率优化 + CDQ分治

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

  3. 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的数量. 然后就很明显了...平衡 ...

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

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

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

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

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

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

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

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

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

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

  9. 【BZOJ1492】[NOI2007]货币兑换Cash 斜率优化+cdq分治

    [BZOJ10492][NOI2007]货币兑换Cash Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下简称B券).每 ...

随机推荐

  1. Beat冲刺报告---Day0

    Beta阶段报告---Day0 1.需要改进完善的功能   我们上一阶段开发由于开发时间匆忙,对于爬虫耗时的优化没有考虑.优化的空间我在Alpha阶段的总结报告里说过,具体看下图.   这张图显示出爱 ...

  2. 需求分析&原型设计

    需求分析&原型设计 需求分析 访问软件项目真实用户 首先本项目的用户是这个需要做简单四则运算的用户(我们团队通过对家里有三四年级小学生(需要做简单四则运算)的简单采访):反映了几个主要的问题: ...

  3. scrapy crawl rules设置

    rules = [ Rule(SgmlLinkExtractor(allow=('/u012150179/article/details'), restrict_xpaths=('//li[@clas ...

  4. iOS开发所有KeyboardType与图片对应展示

    1.UIKeyboardTypeAlphabet 2.UIKeyboardTypeASCIICapable 3.UIKeyboardTypeDecimalPad  4.UIKeyboardTypeDe ...

  5. 日志 --BUG记录

    2014-12-15日 在做520wawa的免费推广   部署web应用时 错把path设置为"/*",导致启动tomcat时,导致错误 <Context path=&quo ...

  6. Flask 测试

    测试是每个应用系统发布前必须经历的步骤,自动化测试对测试效率的提高也是毋庸置疑的.对于Flask应用来说,当然可以使用Web自动化测试工具,比如Selenium等来测.Flask官方推荐的自动化测试方 ...

  7. android 时间获取以及时间格式化

    Android中获取系统时间有多种方法,可分为Java中Calendar类获取,java.util.date类实现,还有android中Time实现 现总结如下: 方法一: void getTime1 ...

  8. threadlocal原理及常用应用场景

    1.深入解析ThreadLocal类 ThreadLocal类提供的几个方法: public T get() { } public void set(T value) { } public void  ...

  9. Python内置函数(52)——getattr

    英文文档: getattr(object, name[, default]) Return the value of the named attribute of object. name must ...

  10. ELK学习总结(2-5)elk的版本控制

    ----------------------------------------------------------------- 1.悲观锁和乐观锁 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据 ...