zoukankan      html  css  js  c++  java
  • 【BZOJ】1492: [NOI2007]货币兑换Cash

    【题意】初始资金s,有两种金券A和B,第i天,买入时将投入的资金购买比例为rate[i]的两种股票,卖出时将持有的一定比例的两种股票卖出,第i天股票价格为A[i],B[i],求最大获利。n<=100000。

    【算法】动态规划+斜率优化(CDQ分治)

    【题解】为了最大获利,每次交易一定是全部买进和全部卖出。

    令s[i]表示前i天的最大获利,f[i]表示第i天能购买的最多A股数,g[i]=f[i]/rate[i]表示第i天能购买的最多B股数。

    s[i]=max{ s[i-1] , f[j]*A[i]+g[j]*B[i] },j<i。

    g[i]=s[i]/(A[i]*rate[i]+B[i])

    f[i]=g[i]*rate[i]

    对于决策j和k,假设f[j]<f[k],当k优于j时有:

    f[j]*A[i]+g[j]*B[i]<f[k]*A[i]+g[k]*B[i]

    移向得(g[j]-g[k])/(f[j]-f[k])>-A[i]/B[i],令k[i]=-A[i]/B[i],所以:

    对于满足f[j]<f[k]的决策j和k,满足(g[j]-g[k])/(f[j]-f[k])>k[i]时决策k优于决策j。

    然后用CDQ分治维护动态上凸包,按阶段分治,左子区间按x[]排序构造凸包,右子区间按k[]排序顺序决策。

    具体过程见:CDQ分治优化动态规划

    复杂度O(n log n)。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=100010;
    const double eps=1e-10,inf=1000000000000;
    double s[maxn];
    int n,st[maxn];
    struct cyc{int id;double A,B,r,k,x,y;}a[maxn],b[maxn];
    bool cmp(cyc a,cyc b){return a.k>b.k;}
    double k(int A,int B){
        if(fabs(a[A].x-a[B].x)<eps){if(a[B].y<a[A].y)return -inf;else return inf;}
        return (a[A].y-a[B].y)/(a[A].x-a[B].x);
    }    
    void CDQ(int l,int r){
        if(l==r){
            s[l]=max(s[l],s[l-1]);
            a[l].y=s[l]/(a[l].A*a[l].r+a[l].B);
            a[l].x=a[l].y*a[l].r;
            return;
        }
        int mid=(l+r)>>1;
        int x1=l-1,x2=mid;
        for(int i=l;i<=r;i++)if(a[i].id<=mid)b[++x1]=a[i];else b[++x2]=a[i];
        for(int i=l;i<=r;i++)a[i]=b[i];
        CDQ(l,mid);
        int top=0;
        for(int i=l;i<=mid;i++){
            while(top>1&&k(st[top],i)>k(st[top-1],st[top]))top--;
            st[++top]=i;
        }
        int x=1;
        for(int i=mid+1;i<=r;i++){
            while(x<top&&k(st[x],st[x+1])>a[i].k)x++;
            s[a[i].id]=max(s[a[i].id],a[st[x]].x*a[i].A+a[st[x]].y*a[i].B);
        }
        CDQ(mid+1,r);
        x1=l,x2=mid+1;
        for(int i=l;i<=r;i++){
            if(x1>mid)b[i]=a[x2++];else
            if(x2>r)b[i]=a[x1++];else
            if(a[x1].x<a[x2].x)b[i]=a[x1++];else b[i]=a[x2++];
        }
        for(int i=l;i<=r;i++)a[i]=b[i];
    }
    int main(){
        scanf("%d%lf",&n,&s[0]);
        for(int i=1;i<=n;i++){
            a[i].id=i;
            scanf("%lf%lf%lf",&a[i].A,&a[i].B,&a[i].r);
            a[i].k=-a[i].A/a[i].B;
        }
        sort(a+1,a+n+1,cmp);
        CDQ(1,n);
        printf("%.3lf",s[n]);
        return 0;
    }
    View Code
  • 相关阅读:
    redis实现电商购物车
    redis应用于各种结构型和非结构型高热度数据访问加速
    Redis控制热点新闻的实效性
    Redis实现分表操作id唯一
    KrakenD网关V1.0.0文档初步翻译
    CentOS7环境下安装Chrome
    七夕秀恩爱新姿势!这波操作我给十分!
    小程序&#183;云开发实战
    小程序&#183;云开发实战
    小程序云开发实战
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8242723.html
Copyright © 2011-2022 走看看