BZOJ 1492: [NOI2007]货币兑换Cash( dp + 平衡树 )
2016-01-24 15:12
447 查看
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 MBSubmit: 2843 Solved: 1201
[Submit][Status][Discuss]
Description
Input
第一行两个正整数N、S,分别表示小Y 能预知的天数以及初始时拥有的钱数。 接下来N 行,第K 行三个实数AK、BK、RateK,意义如题目中所述Output
只有一个实数MaxProfit,表示第N 天的操作结束时能够获得的最大的金钱 数目。答案保留3 位小数。Sample Input
3 1001 1 1
1 2 2
2 2 3
Sample Output
225.000HINT
测试数据设计使得精度误差不会超过10-7。
对于40%的测试数据,满足N ≤ 10;
对于60%的测试数据,满足N ≤ 1 000;
对于100%的测试数据,满足N ≤ 100 000;
Source
相关文章推荐
- hdu 1005 number sequence
- Python+Django+Mysql+Eclipse开发环境配置(Windows)
- 1.24 Java周末总结 ①乘法数据的溢出 ②测试random随机数几率是否相等 ③判断字符串是否为纯数字
- 在一个范围点击空白,则做出相应的操作
- java.time时间/日期API
- C++:【常见面试题】String类的写法
- 51Nod 1499 进制转化问题。
- Hdu 2094 产生冠军
- USACO-Section 3.1-PROB Humble Numbers
- A*算法解八数码问题
- tiny-cnn开源库的使用(MNIST)
- 简单而又神奇的隐马尔科夫模型(HMM)
- tiny-cnn开源库的使用(MNIST)
- Redis keys命令
- 计算机视觉代码合集
- LA3708 - Graveyard (等比缩放)
- 计算机视觉代码合集
- Ubuntu 15.10安装mongodb
- C++builder调用存储过程
- 经典大数据架构案例:酷狗音乐的大数据平台重构