dp(i) = max(dp(i-1), x[j]*a[i]+y[j]*b[i]), 0<j<i. x, y表示某天拥有的最多钱去买金券, 金券a和金券b的数量. 然后就很明显了...平衡树维护上凸壳, 询问时就在凸壳上二分...时间复杂度O(NlogN)

-----------------------------------------------------------------------------------------------

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
 
using namespace std;
 
#define K(a, b) ((a.y - b.y) / (a.x - b.x))
 
const int maxn = 100009;
const double eps = 1e-7;
const double INF = 1e100;
 
double dp, A, B, R, K;
int N;
 
struct P {
double x, y;
P(double _x = 0, double _y = 0) : x(_x), y(_y) {
}
bool operator < (const P &p) const {
return x < p.x;
}
bool operator == (const P &p) const {
return fabs(x - p.x) < eps && fabs(y - p.y) < eps;
}
} p;
 
struct Node {
Node* ch[2];
double lk, rk;
int r;
P p;
} pool[maxn], *pt, *Root, *Null;
 
void Init_Treap() {
pt = pool;
pt->ch[0] = pt->ch[1] = pt;
pt->p = P(-INF, -INF);
Root = Null = pt++;
}
 
void Rotate(Node*&t, int d) {
Node* o = t->ch[d ^ 1];
t->ch[d ^ 1] = o->ch[d];
o->ch[d] = t;
t = o;
}
 
void Insert(Node*&t) {
if(t == Null) {
(t = pt++)->p = p, t->r = rand();
t->ch[0] = t->ch[1] = Null;
} else {
int d = (t->p < p);
Insert(t->ch[d]);
if(t->ch[d]->r > t->r) Rotate(t, d ^ 1);
}
}
 
void Delete(Node*&t) {
int d = (p == t->p ? -1 : (t->p < p));
if(d == -1) {
if(t->ch[0] != Null && t->ch[1] != Null) {
int _d = (t->ch[0]->r > t->ch[1]->r);
Rotate(t, _d), Delete(t->ch[_d]);
} else
t = (t->ch[0] != Null ? t->ch[0] : t->ch[1]);
} else 
Delete(t->ch[d]);
}
 
Node* Pred(P &p) {
Node* ret = Null;
for(Node* o = Root; o != Null; ) if(o->p < p)
ret = o, o = o->ch[1];
else
o = o->ch[0];
return ret;
}
 
Node* Succ(P &p) {
Node* ret = Null;
for(Node* o = Root; o != Null; ) if(p < o->p)
ret = o, o = o->ch[0];
else
o = o->ch[1];
return ret;
}
 
Node* Find(P &p) {
for(Node* t = Root; t != Null; ) {
if(fabs(t->p.x - p.x) < eps) return t;
t = (p.x < t->p.x ? t->ch[0] : t->ch[1]);
}
return 0;
}
 
P Select(Node*&t) {
if(t->r == -1) return Select(t->ch[1]);
if(t->r == -2) return Select(t->ch[0]);
if(K - t->lk < eps && t->rk - K < eps) return t->p;
return K - t->lk > eps ? Select(t->ch[0]) : Select(t->ch[1]);
}
 
void Init() {
Init_Treap();
p = P(0, -INF), Insert(Root);
p = P(1e10, -INF), Insert(Root);
Node* t = pt;
(--t)->r = -2, (--t)->r = -1;
}
 
void Add() {
double b = dp / (A * R + B), a = b * R;
P o = P(a, b);
Node *t = Find(o);
if(t) {
if(t->p.y - o.y > eps) return;
p = t->p, Delete(Root);
}
Node *L = Pred(o), *R = Succ(o);
if(R->p == o || K(o, R->p) - K(o, L->p) > eps) return;
for(Node* LL = Pred(L->p); LL != Null; ) {
if(K(o, L->p) - K(L->p, LL->p) > eps)
p = L->p, Delete(Root);
else
break;
L = LL, LL = Pred(L->p);
}
pt->lk = L->rk = K(L->p, o);
for(Node* RR = Succ(R->p); RR != Null; ) {
if(K(RR->p, R->p) - K(R->p, o) > eps)
p = R->p, Delete(Root);
else
break;
R = RR, RR = Succ(R->p);
}
R->lk = pt->rk = K(R->p, o);
p = o, Insert(Root);
}
 
void Work() {
scanf("%d%lf", &N, &dp);
for(int i = 0; i < N; i++) {
scanf("%lf%lf%lf", &A, &B, &R);
if(i) {
K = -A / B;
P o = Select(Root);
dp = max(dp, A * o.x + B * o.y);
}
Add();
}
printf("%.3lf\n", dp);
}
 
int main() {
Init();
Work();
return 0;
}

-----------------------------------------------------------------------------------------------

1492: [NOI2007]货币兑换Cash

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 2843  Solved: 1201
[Submit][Status][Discuss]

Description

Input

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

Output

只有一个实数MaxProfit,表示第N 天的操作结束时能够获得的最大的金钱 数目。答案保留3 位小数。

Sample Input

3 100
1 1 1
1 2 2
2 2 3

Sample Output

225.000

HINT

测试数据设计使得精度误差不会超过10-7。
对于40%的测试数据,满足N ≤ 10;
对于60%的测试数据,满足N ≤ 1 000;
对于100%的测试数据,满足N ≤ 100 000;

Source

BZOJ 1492: [NOI2007]货币兑换Cash( dp + 平衡树 )的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. ●BZOJ 1492 [NOI2007]货币兑换Cash

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

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

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

  8. BZOJ 1492: [NOI2007]货币兑换Cash 斜率优化 + splay动态维护凸包

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

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

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

随机推荐

  1. [置顶] java web 动态服务器

    写了一个java web 动态服务器,主要通过内部类来实现,动态类使用了外部类,采用了 classforname 实例化,动态类的构造方法不能带参数, 效果都出来了,分享给有需要的 朋友.判断做的不够 ...

  2. 最简单的视音频播放演示样例4:Direct3D播放RGB(通过Texture)

    ===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...

  3. 相比于python2.6,python3.0的新特性。

    这篇文章主要介绍了相比于python2.6,python3.0的新特性.更详细的介绍请参见python3.0的文档. Common Stumbling Blocks 本段简单的列出容易使人出错的变动. ...

  4. php汉字截取

    /** * 截取HTML,并自动补全闭合 * @param $html * @param $length * @param $end */ function subHtml($html,$length ...

  5. Android开发问题汇总(持续更新)

    在Android开发中,总会有一些很小的问题.由于我们的不仔细,很容易忽略掉,从而导致在该问题上花费了很多的时间,造成工作进度的延迟. 为此,在这里做一下记录,避免再次浪费许多时间在这些问题上. 1. ...

  6. background-size使用

    background-size: left center | 0% 50% | cover | contain backgound-size: left center | 0% 50%; 这个指的是背 ...

  7. jquery插件anccordion

    (function(){ $.fn.YAccordion=function(options){ var settings={ trigger:'click', speed:300, }; if(opt ...

  8. Cmd批处理语法实例

    @echo on :循环获取指定目录下以php为后缀的文件,且重命名后缀为html :for /r "E:\aaa\web" %%v in (*.php) do ren " ...

  9. 周末苦逼码代码,为css3的强大所颤抖了

    周末小哥我看完了几个星期没追的行尸走肉和生活大爆炸(感谢大A站!),感觉生活真的好空虚,没想到我现在居然会对游戏失去了兴趣!!!代码的魔力真的是无法用语言形容...(我真假...)百无聊赖,在电脑上装 ...

  10. php 常用经验

    1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量, 单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的”函数”(译注:PHP手 ...