<CDQ分治> 货币兑换Cash [HYSBZ - 1492]

E - 货币兑换Cash HYSBZ - 1492

\(N,S​\),分别表示天数以及初始时拥有的钱数

接下来N行,每行三个实数\(A_i,B_i,Rate_i\),表示第\(i\)天A券和B券的汇率,和购买时要按\(a:b=rate\)的数量比购买

每天都可以随时买入和卖出,买入规则如上,卖出时A,B按同一百分比卖出,求最后一天最多能获得多少钱

\(0<AK≤10;0<BK≤10;0<RateK≤100;ans≤10^9\)(实数读入)

【提示】

1.输入文件可能很大,请采用快速的读入方式。

2.必然存在一种最优的买卖方案满足:

每次买进操作使用完所有的人民币;

每次卖出操作卖出所有的金券。

题解

注意提示, 买光或买光

  • 每天手里的券可以兑换成钱表示(唯一表示), 因为当天买之前有这么多钱, 买光只有一种买法
  • 每天手里的钱可以用钱表示

所以用\(f[i]\)表示当天最大的钱/券换算成的钱

  • 继承pre的价值 : \(f[i] = max(f[pre])​\)
  • pre买,i卖 : \(f[i] = max(f[pre] / (rate[pre] * a[pre] + b[pre]) * rate[pre] * a[i] + f[pre] / (rate[pre] * a[pre] + b[pre]) * b[i]);\)

\(x = f[pre] / (rate[pre] * a[pre] + b[pre]) * rate[pre];\\​\)
\(y = f[pre] / (rate[pre] * a[pre] + b[pre]);\\​\)
\(y = -\frac{a[i]}{b[i]}x + \frac{f[i]}{b[i]}​\)

其中\((x_{pre},y_{pre})​\)都只含有关于\(pre​\)的信息

所以相当于拿一条斜率为\(-\frac{a[i]}{b[i]}\)去切\((x_{pre},y_{pre})\),得到的截距越大, \(f[i]\)越大

注意到如果以\(j\)继承比\(k\)更优,则\((x_j,y_j)与(x_k,y_k)\)的斜率要\(>-\frac{a[i]}{b[i]}\)(画图)

所以当\((mid+1,r)\)斜率递减时,可以从左到右依次在\((l,mid)\)组成的上凸线上找到优的继承点

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
const double EPS = 1e-9;

inline int in()
{
    int x = 0, flag = 1; char ch = getchar();
    while (ch < '0' || ch > '9') { if (ch == '-') flag = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
    return x * flag;
}

int n, s, tot;
double f[MAXN];
struct Node
{
    double a, b, rate, k, x, y;
    int id ;
} q[MAXN], p[MAXN], stk[MAXN];

bool cmpxy(Node A, Node B) { return (A.x == B.x) ? (A.y < B.y) : (A.x < B.x); }
bool cmpk(Node A, Node B) { return A.k > B.k; }
double getk(Node A, Node B)
{
    if (fabs(A.x - B.x) < EPS) return 1e20;
    return (A.y - B.y) / (A.x - B.x);
}
void solve(int l, int r)
{
    if (l == r)
    {
        f[l] = max(f[l - 1], f[l]);
        p[l].y = f[l] / (p[l].rate * p[l].a + p[l].b);
        p[l].x = p[l].y * p[l].rate;
        return ;
    }
    int mid = (l + r) >> 1;
    solve(l, mid);
    for (int i = l; i <= r; i ++) q[i] = p[i];
    sort(q + l, q + mid + 1, cmpxy);
    sort(q + mid + 1, q + r + 1, cmpk);
    int top = 0;
    for (int i = l; i <= mid; i ++)
    {
        while (top > 1 && getk(stk[top - 1], stk[top]) < getk(stk[top], q[i]) + EPS) top --;
        stk[++top] = q[i];
    }
    for (int i = mid + 1, j = 1; i <= r; i ++)
    {
        while (j + 1 <= top && q[i].k < getk(stk[j], stk[j + 1]) + EPS) j ++;
        f[q[i].id] = max(f[q[i].id], stk[j].x * q[i].a + stk[j].y * q[i].b);
    }
    solve(mid + 1, r);
}

int main()
{
    n = in(), s = in();
    f[0] = s;
    for (int i = 1; i <= n; i ++)
    {
        double a, b, rate;
        scanf("%lf%lf%lf", &a, &b, &rate);
        p[i] = (Node) { a, b, rate, - a / b, 0, 0, i };
    }
    solve(1, n);
    printf("%.3lf\n", f[n]);
    return 0;
}
/*
 */

转载于:https://www.cnblogs.com/ikihsiguoyr/p/10569508.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值