1. 程式人生 > >bzoj3963[WF2011]MachineWorks cdq分治+斜率優化dp

bzoj3963[WF2011]MachineWorks cdq分治+斜率優化dp

包含 page 斜率優化 font www. fine 天使 int 的人

3963: [WF2011]MachineWorks

Time Limit: 30 Sec Memory Limit: 256 MB
Submit: 270 Solved: 80
[Submit][Status][Discuss]

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

轉移並不滿足單調啊,所以需要用cdq分治來維護單調的轉移
也可以寫splay
這篇博客寫得不錯http://www.cnblogs.com/zj75211/p/8148800.html

 1
#include<bits/stdc++.h> 2 #define N 100050 3 #define ll long long 4 #define inf 2147483647 5 using namespace std; 6 int n,m,D,s[N];ll f[N]; 7 struct date{int d,p,r,g,id;}q[N],a[N]; 8 //struct point{int x;ll y;}p[N],b[N]; 9 bool cmp1(date a,date b){return a.d<b.d;} 10 ll X(int i){ 11 return q[i].r+f[q[i].id]-q[i].p-(ll)q[i].g*(q[i].d+1); 12 } 13 int Y(int i){ 14 return q[i].g; 15 } 16 17 double G(int i,int j){ 18 // if(Y(i)==Y(j))return (double)(X(i)>X(j)?inf:-inf); 19 return (double)(X(i)-X(j))/(double)(Y(i)-Y(j)); 20 } 21 void solve(int l,int r){ 22 if(l>r)return; 23 if(l==r){ 24 f[l]=max(f[l],f[l-1]); 25 return; 26 } 27 int mid=(l+r)>>1; 28 int p1=l,p2=mid+1; 29 //for(int i=l;i<=r;i++)q[i]=a[i]; 30 solve(l,mid);int tp=0,h=1; 31 for(int i=l;i<=mid;i++){ 32 if(q[i].p>f[q[i].id])continue; 33 if(Y(i)==Y(s[tp])&&tp){ 34 if(X(i)>X(s[tp]))tp--; 35 else continue; 36 } 37 while(tp>1&&G(s[tp],s[tp-1])<=G(i,s[tp]))tp--; 38 s[++tp]=i; 39 } 40 for(int i=mid+1;i<=r;i++){ 41 while(h<tp&&G(s[h],s[h+1])>=-q[i].d)h++; 42 f[i]=max(f[i],f[i-1]); 43 if(h<=tp)f[i]=max(f[i],f[q[s[h]].id]-q[s[h]].p+q[s[h]].r+(ll)q[s[h]].g*(q[i].d-q[s[h]].d-1)); 44 } 45 solve(mid+1,r); 46 p1=l;p2=mid+1; 47 for(int i=l;i<=r;i++){ 48 if(p1<=mid&&q[p1].g<=q[p2].g)a[i]=q[p1++]; 49 else if(p2<=r)a[i]=q[p2++]; 50 else a[i]=q[p1++]; 51 } 52 for(int i=l;i<=r;i++)q[i]=a[i]; 53 } 54 int main(){ 55 int cas=0; 56 while(scanf("%d%d%d",&n,&m,&D)!=EOF){ 57 cas++; 58 if(!n&&!m&&!D)break; 59 memset(f,-1,sizeof(f)); 60 f[1]=f[0]=m;int d,p,r,g; 61 for(int i=1;i<=n;i++) 62 scanf("%d%d%d%d",&d,&p,&r,&g), 63 q[i]=(date){d,p,r,g,i}; 64 q[++n]=(date){D+1,0,0,0,n}; 65 sort(q+1,q+1+n,cmp1); 66 for(int i=1;i<=n;i++)q[i].id=i; 67 solve(1,n); 68 printf("Case %d: %lld\n",cas,f[n]); 69 } 70 return 0; 71 }

bzoj3963[WF2011]MachineWorks cdq分治+斜率優化dp