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. PHP中静态方法和非静态方法的相互调用

    在PHP的非静态方法中可以调用静态方法 class test{ public static function strPrint(){ echo 'this is strPrint static fun ...

  2. DevExpress中ChartControl柱状图(Bar)用法

    我的数据 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 chartControl1.Series.Clear(); ...

  3. SSRS(rdl报表)分页显示表头和冻结表头

    <TablixRowHierarchy>          <TablixMembers>            <TablixMember>            ...

  4. java 多线程学习(一)

    public class ThreadA extends Thread { ; public ThreadA() { super("ThreadID:" + (++threadID ...

  5. day9_python学习笔记_chapter12_模块

    1. 名称空间加载顺序: 首先加载内建名称空间,他由__builtin模块中的名字构成.然后加载执行模块的全局名称空间,他会在模块开始执行后变为活动名称空间.如 果在执行期间调用了一个函数,那么将创建 ...

  6. 再谈PHP、Python与Ruby

    一句话总结 简单地总结: 假如你想帮他尽快找个活儿,赚到钱,推荐PHP. 假如你想让他成为一个高效工程师,推荐 Python. 假如你想让他爱上他的工作,推荐 Ruby. 语言的选择 编程语言非常重要 ...

  7. python初学笔记(三)

    Unicode字符串 字符串还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节 (byte),所以,一 ...

  8. CSS自学笔记(2):CSS语法

    CSS的语法规则主要有两个分构成选择器和声明(声明问一条或者多条). selector {declaration1; declaration2; ... declarationN } 选择器(selc ...

  9. “Options模式”下各种类型的Options对象是如何绑定的?

    “Options模式”下各种类型的Options对象是如何绑定的? 旨在生成Options对象的配置绑定实现在IConfiguration接口的扩展方法Bind上.配置绑定的目标类型可以是一个简单的基 ...

  10. Linux 分区初始化为物理卷,把物理卷加入卷组

    用到的命令有 1.pvcreate (physical volume create) 2.vgcreate (volume group create) 例子1:创建物理卷 pvcreate /dev/ ...