• 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的数量. 然后就很明显了...平衡树维护上凸壳, 询问时就在凸壳上二分...时间复杂度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 ", 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

  • 相关阅读:
    DataSet主副表关系应注意的问题
    [转载]Converting a bitmap to a byte array
    通用验证脚本
    AG_E_RUNTIME_METHOD : CreateFromXaml错误的及解决
    Nginx打开目录浏览功能(autoindex)
    SQL语句执行时间
    有关cookies使用方法
    测试一下咯。这是水笔!
    Java注解与枚举简单练习
    ElasticSearch练习
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5155186.html
Copyright © 2020-2023  润新知