【BZOJ3963】[WF2011]MachineWorks
Description
Input
Output
Sample Input
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
题解:来来来,先列式子:设f[i]表示在还没有买机器i(想买还没买)时,所能得到的最大收益,那么有:
f[i]=max{f[j]+R[j]-P[j]+G[j]*(D[i]-D[j]-1)} (D[j]<D[i],f[j]>=P[j])
移项搞一搞,感觉像是斜率优化,但是好像x不单调?依旧套用cash那题的做法。上cdq分治,左边按x单调,右边按k单调,用左边更新右边即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,h,t,T;
int q[maxn];
struct node
{ll P,R,D,G,f;
}s[maxn],p[maxn];
ll X(int a)
{return s[a].G;
}
ll Y(int a)
{return s[a].P-s[a].R+s[a].G+s[a].G*s[a].D-s[a].f;
}
int rd()
{int ret=0,f=1; char gc=getchar();while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();return ret*f;
}
bool cmpx(node a,node b)
{return a.G<b.G;
}
bool cmpk(node a,node b)
{return a.D<b.D;
}
long double slope(int a,int b)
{if(X(a)==X(b)) return (long double)(Y(a)<Y(b)?2147483647:-2147483647);return (long double)(Y(b)-Y(a))/(X(b)-X(a));
}
void solve(int l,int r)
{if(l==r){s[l].f=max(s[l].f,s[l-1].f);return ;}int mid=l+r>>1,i,h1=l,h2=mid+1;solve(l,mid);h=1,t=0;for(i=l;i<=mid;i++){if(s[i].f<s[i].P) continue;while(h<t&&slope(q[t-1],q[t])>=slope(q[t],i)) t--;q[++t]=i;}for(i=mid+1;i<=r;i++){while(h<t&&slope(q[h],q[h+1])<=s[i].D) h++;s[i].f=max(s[i].f,s[i-1].f);if(h<=t) s[i].f=max(s[i].f,s[q[h]].f-s[q[h]].P+s[q[h]].R+s[q[h]].G*(s[i].D-s[q[h]].D-1));}solve(mid+1,r);for(i=l;i<=r;i++){if(h1<=mid&&(h2>r||X(h1)<=X(h2))) p[i]=s[h1++];else p[i]=s[h2++];}for(i=l;i<=r;i++) s[i]=p[i];
}
int main()
{while(1){memset(s,0,sizeof(s));n=rd(),s[0].f=rd(),s[n+1].D=rd()+1;if(!n) return 0;int i;for(i=1;i<=n;i++) s[i].D=rd(),s[i].P=rd(),s[i].R=rd(),s[i].G=rd();n++;sort(s,s+n+1,cmpk);solve(0,n);sort(s,s+n+1,cmpk);printf("Case %d: %lld\n",++T,s[n].f);}
}