[BZOJ3963] [ACM-WF2011] MachineWorks (CDQ divide and conquer + slope optimization)

Keywords: less

Description

You are the manager of Arbitrary Complex Machines (ACM), which uses more advanced machinery to produce advanced machines. The original production machine has broken down, so you have to buy a new one for the company. Your task is to get as much benefit as possible during the transition period. During this period, you have to buy and sell machines, and when the machines are owned by ACM, you manipulate them to make profits. Because of space constraints, ACM can only have one machine at most at any time.
During the transition period, there are several machines that may be sold. As an expert in advanced machines, for each Mi, you already know its price Pi and the date Di can be purchased. Note that if you don't buy the machine Mi on Di Day, other people will buy the machine, that is to say, you won't have a chance to buy the machine in the future. If ACM costs less than the price of a machine, then obviously you can't buy it.
If you buy the machine Mi on Di day, ACM can start using it on (Di)+1 day. Every day you use this machine, you can generate Gi dollars for the company.
You can decide to sell the machine at a discount someday after you buy it. The acquisition market has a discount price Ri for each machine. You can't use the machine on the day it's sold, but you can buy a new one on the day it's sold.
At the end of the transition period, ACM will sell the machines it currently owns. Your task is to maximize the revenue ACM will receive during the transition period.

Input

The input contains several sets of test cases. The first row of each set of test cases has three positive integers N, C and D. N is the number of machines that will be sold (N <= 10 ^ 5), C is the amount of dollars that the company owns at the beginning of the transition period (C <= 10 ^ 9), and D is the number of days that the transition period lasts (D <= 10 ^ 9).
The following N rows each describe the situation of a machine. Each line has four positive integers, Di,Pi,Ri and Gi, representing the time the machine was sold, the amount of dollars needed to buy the machine, the discount price for selling the machine, and the profit that could be made from using the machine. These numbers satisfy 1 <= Di <= D, 1 <= Ri < Pi <= 10 ^ 9 and 1 <= Gi <= 10 ^ 9.
The last set of test cases is followed by a row of three zeros representing input data.

Output

For each set of test cases, output the number of test cases, and then give ACM the maximum amount of dollars it can get at the end of day D+1.
Please follow the sample output given below.

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

Explanation:
Poke here
I think this is a very good article, very clear, here I recommend it.
The feeling proves that monotony is still too weak to prove, only guess== b.
The code is as follows:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll long long
#define inf 0x7f7f7f7f
#define N 100005
#define pii pair<int,ll> 
#define X first
#define Y second
using namespace std;
ll read()
{
    ll x=0,f=1;
    char c=getchar();
    while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c<='9' && c>='0') {x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct nod
{
    int d,p,r,g;
    bool operator < (const nod& b) const {return d<b.d;}
}a[N];
int cas,n,d;
ll f[N];  
pii q[N],b[N];  
ll h(int j) 
{  
    return f[j]+(ll)a[j].r-(ll)a[j].p-(ll)a[j].g*(ll)(a[j].d + 1);  
}  
int get_slope(pii a, pii b, pii c) 
{  
    ll xa=b.X-a.X,xb=c.X-a.X,ya=b.Y-a.Y,yb=c.Y-a.Y;  
    double tmp=(double)xa*yb-(double)xb*ya;  
    return tmp<0;  
}  
void cdq(int l,int r)
{
    if(l>=r) return;
    int mid=(l+r)>>1;
    cdq(l,mid);
    int cnta=0,cntb=0;
    for(int i=l;i<=mid;i++)
    if(f[i]>=a[i].p) q[cnta++]=pii(a[i].g,h(i));
    sort(q,q+cnta);
    for(int i=0;i<cnta;i++)
    {
        while(cntb>1 && !get_slope(b[cntb-1],b[cntb],q[i])) 
        cntb--;
        b[++cntb]=q[i];
    }
    int j=0;
    for(int i=mid+1;i<=r;i++)
    {
        ll x=a[i].d;
        ll a1,a2,b1,b2;
        while(j<cntb)
        {
            a1=b[j].X,a2=b[j+1].X;
            b1=b[j].Y,b2=b[j+1].Y;
            if(a1*x+b1>=a2*x+b2) break;
            j++;
        }
        f[i]=max(f[i],(ll)b[j].X*x+(ll)b[j].Y);
    }
    cdq(mid+1,r);
}
int main()
{
    while(1)
    {
        n=read(),f[0]=read(),d=read();
        if(!n) break;
        for(int i=1;i<=n;i++) 
        {
            a[i].d=read(),a[i].p=read();
            a[i].r=read(),a[i].g=read();
        }
        sort(a+1,a+1+n);
        a[++n].d=d+1,a[n].p=a[n].g=0;
        for(int i=1;i<=n;i++) f[i]=f[0];
        cdq(0,n);
        printf("Case %d: %lld\n",++cas,f[n]);
    }
    return 0;
}

Posted by GremlinP1R on Mon, 22 Apr 2019 02:30:34 -0700