zoukankan      html  css  js  c++  java
  • BZOJ_3963_[WF2011]MachineWorks_斜率优化+CDQ分治

    BZOJ_3963_[WF2011]MachineWorks_斜率优化+CDQ分治

    Description

    你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先进的机械设备生产先进的机器。原来的那一台生产机器已经坏了,所以你要去为公司买一台新的生产机器。你的任务是在转型期内尽可能得到更大的收益。在这段时间内,你要买卖机器,并且当机器被ACM公司拥有的时候,操控这些机器以获取利润。因为空间的限制,ACM公司在任何时候都只能最多拥有一台机器。
    在转型期内,有若干台可能卖出的机器。作为先进机器的专家,对于每台机器Mi,你已经知道了其价格Pi和可以买入的日期Di。注意,如果不在第Di天买入机器Mi,那么别的人也会买走这一台机器,也就是说,以后你将没有机会购买这台机器了。如果ACM的钱低于一台机器的价格,那么你显然不可能买到这一台机器。
    如果你在第Di天买入了机器Mi,那么ACM公司可以从第(Di)+1天开始使用这一台机器。每使用这台机器一天,就可以为公司创造出Gi美元的收益。
    你可以决定要在买入之后的某一天,以一定的折扣价卖出这一台机器。收购市场对于每一台机器,都有一个折扣价Ri。你不能在卖出的那一天使用机器,但是你可以在卖出的那一天再买入一台新的。
    在转型期结束后,ACM公司会卖掉当前所拥有的机器。你的任务就是最大化转型期间ACM公司可以得到的收入。

    Input

    输入包含若干组测试用例。每一组测试用例的第一行有3个正整数N,C和D。N是将会卖出的机器的台数(N<=10^5),C是在转型期开始时公司拥有的美元数量(C<=10^9),D是转型期持续的天数(D<=10^9)。
    之后的N行每一行描述了一台机器的情况。每一行有4个正整数Di,Pi,Ri和Gi,分别表示这台机器卖出的时间,购买这台机器需要的美元数量,卖出这台机器的折扣价和使用这台机器可以得到的利润。这些数字满足1<=Di<=D,1<=Ri<Pi<=10^9且1<=Gi<=10^9.
    最后一组测试用例后面的一行由3个0组成,表示输入数据。

    Output

    对于每一组测试用例,输出测试用例的编号,之后给出ACM公司在第D+1天结束后可以得到的最大数量的美元。
    请依照下面给出的样例输出。

    Sample Input

    6 10 20
    6 12 1 3
    1 9 1 2
    3 2 1 2
    8 20 5 4
    4 11 7 4
    2 10 9 1
    0 0 0

    Sample Output

    Case 1: 44

    设F[i]表示考虑完前i台机器的最大收入。
    那么F[i]=F[j]-P[i]+(D[i]-D[j]-1)*G[j]+R[j]  (F[i]>=P[i])。
    和货币兑换类似,不过那道题我写的时候是把决策点当成直线,每次用横坐标去切。
    这道题我试着把决策点当做点,每次用直线查询。
    变成斜率的形式后发现查询的斜率单调,然而每次插入点的横坐标不单调。
    于是用CDQ分治。左边插入的横坐标单调,对左边建凸壳,扫一遍更新右边的。
    注意初始化。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    typedef double f2;
    #define N 200050
    #define eps 1e-6
    #define mem(x) memset(x,0,sizeof(x))
    ll f[N],D[N],P[N],R[N],G[N],C;
    int n,Case,S[N],t[N],tmp[N];
    #define Y(j) (f[j]-P[j]-D[j]*G[j]-G[j]+R[j])
    #define X(j) (G[j])
    #define K(i) (-D[i])
    struct A {
        ll d,p,r,g;
        bool operator < (const A &x) const {
            return d<x.d;
        }
    }a[N];
    f2 getK(int p1,int p2) {
        if(fabs(X(p2)-X(p1))<eps) return Y(p2)>Y(p1)?1e15:-1e15;
        return (1.0*Y(p2)-Y(p1))/(X(p2)-X(p1));
    }
    void solve(int l,int r) {
        if(l==r) return ;
        int mid=(l+r)>>1;
        solve(l,mid);
        int i,j,k;
        int top=0;
        for(i=l;i<=mid;i++) {
            if(f[t[i]]<P[t[i]]) continue;
            while(top>1&&getK(S[top-1],S[top])<=getK(S[top-1],t[i])) top--;
            S[++top]=t[i];
        }
        for(j=1,i=mid+1;i<=r;i++) {
            while(j<top&&getK(S[j],S[j+1])+eps>=K(t[i])) j++;
            f[t[i]]=max(f[t[i]],Y(S[j])-K(t[i])*X(S[j]));
        }
        solve(mid+1,r);
        i=l,j=l,k=mid+1;
        while(j<=mid&&k<=r) {
            if(X(t[j])<X(t[k])) tmp[i++]=t[j++];
            else tmp[i++]=t[k++];
        }
        while(j<=mid) tmp[i++]=t[j++]; 
        while(k<=r) tmp[i++]=t[k++];
        for(i=l;i<=r;i++) t[i]=tmp[i];
    }
    int work() {
        Case++;
        ll tmp;
        scanf("%d%lld%lld",&n,&C,&tmp); D[n+1]=tmp+1;
        if(n==0) return 0;
        int i,j;
        for(i=1;i<=n;i++) {
            scanf("%lld%lld%lld%lld",&a[i].d,&a[i].p,&a[i].r,&a[i].g);
        }
        /*if(Case!=17) return 1;
        printf("%d %lld %lld
    ",n,C,tmp);
        for(i=1;i<=n;i++) printf("%lld %lld %lld %lld
    ",a[i].d,a[i].p,a[i].r,a[i].g);
        return 0;*/
        sort(a+1,a+n+1);
        for(i=1;i<=n;i++) D[i]=a[i].d,P[i]=a[i].p,R[i]=a[i].r,G[i]=a[i].g,t[i]=i;
        // for(i=1;i<=n;i++) printf("%lld
    ",D[i]);
        n++; f[0]=C; t[n]=n;
        for(i=1;i<=n;i++) f[i]=-K(i)*X(0)+Y(0);
        solve(1,n);
        /*for(i=1;i<=n;i++) {
            for(j=1;j<i;j++) {
                if(f[j]>=P[j])
                f[i]=max(f[i],-K(i)*X(j)+Y(j));
            }
            printf("%lld
    ",f[i]);
        }*/
        printf("Case %d: %lld
    ",Case,f[n]);
        return 1;
    }
    int main() {
        while(1) {
            mem(a); mem(D); mem(P); mem(R); mem(f); mem(G); mem(t); mem(tmp); mem(S);
            int tmp=work();
            if(!tmp) return 0;
        }
    }
    
  • 相关阅读:
    C#--跨线程更新UI--实时显示POST请求传过来的数据
    C#--序列化--JSON和对象互转方法
    C#--winform--Label标签的文字居中
    C#--自定义控件-panel控件(渐变色,文字的绘制)
    C#--自定义控件-开发LED指示灯控件(带闪烁效果)
    艾而特--ModbusTcp通讯测试
    C#--各种方法总结(静态,构造,析构,虚方法,重写方法,抽象,扩展)
    C#--特性的运用试验
    C#--特性基础
    C#--无法将lambda表达式转换为类型‘Delegate’,原因是它不是委托类型
  • 原文地址:https://www.cnblogs.com/suika/p/9220025.html
Copyright © 2011-2022 走看看