zoukankan      html  css  js  c++  java
  • [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包

    1492: [NOI2007]货币兑换Cash

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 5907  Solved: 2377
    [Submit][Status][Discuss]

    Description

    小Y最近在一家金券交易所工作。该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下
    简称B券)。每个持有金券的顾客都有一个自己的帐户。金券的数目可以是一个实数。每天随着市场的起伏波动,
    两种金券都有自己当时的价值,即每一单位金券当天可以兑换的人民币数目。我们记录第 K 天中 A券 和 B券 的
    价值分别为 AK 和 BK(元/单位金券)。为了方便顾客,金券交易所提供了一种非常方便的交易方式:比例交易法
    。比例交易法分为两个方面:(a)卖出金券:顾客提供一个 [0,100] 内的实数 OP 作为卖出比例,其意义为:将
     OP% 的 A券和 OP% 的 B券 以当时的价值兑换为人民币;(b)买入金券:顾客支付 IP 元人民币,交易所将会兑
    换给用户总价值为 IP 的金券,并且,满足提供给顾客的A券和B券的比例在第 K 天恰好为 RateK;例如,假定接
    下来 3 天内的 Ak、Bk、RateK 的变化分别为:
    假定在第一天时,用户手中有 100元 人民币但是没有任何金券。用户可以执行以下的操作:
    注意到,同一天内可以进行多次操作。小Y是一个很有经济头脑的员工,通过较长时间的运作和行情测算,他已经
    知道了未来N天内的A券和B券的价值以及Rate。他还希望能够计算出来,如果开始时拥有S元钱,那么N天后最多能
    够获得多少元钱。

    Input

    输入第一行两个正整数N、S,分别表示小Y能预知的天数以及初始时拥有的钱数。接下来N行,第K行三个实数AK、B
    K、RateK,意义如题目中所述。对于100%的测试数据,满足:0<AK≤10;0<BK≤10;0<RateK≤100;MaxProfit≤1
    0^9。
    【提示】
    1.输入文件可能很大,请采用快速的读入方式。
    2.必然存在一种最优的买卖方案满足:
    每次买进操作使用完所有的人民币;
    每次卖出操作卖出所有的金券。
     

    Output

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

    Sample Input

    3 100
    1 1 1
    1 2 2
    2 2 3

    Sample Output

    225.000

    HINT

    Source

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<algorithm>
     7 #define eps 1e-9
     8 #define maxn 120000
     9 #define inf 2147483647
    10 using namespace std;
    11 struct P {
    12     double x,y;
    13 }p[maxn],pp[maxn];
    14 bool operator <(P t1,P t2){return (t1.x<t2.x+eps)||(fabs(t1.x-t2.x)<=eps&&t1.y<t2.y+eps);}
    15 struct data {
    16     double q,a,b,rate,k;
    17     int pos;
    18 }ask[maxn],askt[maxn];
    19 int n;
    20 double f[maxn];
    21 bool cmp(data t1,data t2) {return t1.k<t2.k;}
    22 double get(int i,int j) {
    23     if(!i) return -inf;
    24     if(!j) return inf;
    25     if(fabs(p[i].x-p[j].x)<=eps) return -inf;
    26     return (p[i].y-p[j].y)/(p[i].x-p[j].x);
    27 }
    28 int sta[maxn];
    29 void cdq(int l,int r) {
    30     if(l==r) {
    31         f[l]=max(f[l-1],f[l]);
    32         p[l].y=f[l]/(ask[l].a*ask[l].rate+ask[l].b);
    33         p[l].x=p[l].y*ask[l].rate;
    34         return;
    35     }
    36     int mid=l+r>>1,l1=l,l2=mid+1;
    37     for(int i=l;i<=r;i++) 
    38         if(ask[i].pos<=mid) askt[l1++]=ask[i];
    39         else askt[l2++]=ask[i];
    40     for(int i=l;i<=r;i++) ask[i]=askt[i];
    41     cdq(l,mid);
    42     int top=0;
    43     for(int i=l;i<=mid;i++) {
    44         while(top>=2&&get(i,sta[top])+eps>get(sta[top],sta[top-1])) top--;
    45         sta[++top]=i;
    46     }
    47     int j=1;
    48     for(int i=r;i>=mid+1;i--) {
    49         while(j<top&&ask[i].k<get(sta[j],sta[j+1])+eps) j++;
    50         f[ask[i].pos]=max(f[ask[i].pos],p[sta[j]].x*ask[i].a+p[sta[j]].y*ask[i].b);
    51     }
    52     cdq(mid+1,r);
    53     l1=l,l2=mid+1;
    54     for(int i=l;i<=r;i++) {
    55         if((p[l1]<p[l2]||l2>r)&&l1<=mid) pp[i]=p[l1++];
    56         else pp[i]=p[l2++];
    57     }
    58     for(int i=l;i<=r;i++) p[i]=pp[i];
    59 }
    60 int main() {
    61     scanf("%d%lf",&n,&f[0]);
    62     for(int i=1;i<=n;i++) {
    63         scanf("%lf%lf%lf",&ask[i].a,&ask[i].b,&ask[i].rate);
    64         ask[i].k=-ask[i].a/ask[i].b;ask[i].pos=i;
    65     }
    66     sort(ask+1,ask+n+1,cmp);
    67     cdq(1,n);
    68     printf("%.3lf
    ",f[n]);
    69 }
    View Code
  • 相关阅读:
    这次面试就差不多了,你有什么问题需要问我呢?
    C++为啥要使用new
    C#读取“我的文档”等特殊系统路径及环境变量
    C++11 Lambda表达汇总总结
    c#计算 坐标点与坐标点之间的距离
    eclipse svn同步资源库时忽略某些不需要提交文件类型和文件夹
    通俗理解TCP/IP协议三次握手四次分手流程
    mysql 免安装版 启动服务马上关闭
    MySQL数据库安装与配置详解
    word 插入的图片被嵌套在文字底下
  • 原文地址:https://www.cnblogs.com/wls001/p/8550491.html
Copyright © 2011-2022 走看看