Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 300000
#define inf 10000000000000009
#define ll long long
using namespace std;
const long double eps = 1e-10;
int root;
int idxx[maxn];
struct Splaytree
{
#define get(x) (ch[f[x]][1]==x)
int cnt;
int ch[maxn][2],f[maxn];
long double X[maxn],Y[maxn],lk[maxn],rk[maxn];
// i 在前, j 在后
long double slope(int i,int j)
{
if(fabs(X[i]-X[j])<=eps) return Y[j]>Y[i] ? (long double)inf : (long double)-inf;
return (Y[i]-Y[j])/(X[i]-X[j]);
}
inline void rotate(int x)
{
int old=f[x],fold=f[old],which=get(x);
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
if(fold) ch[fold][ch[fold][1]==old]=x;
}
inline void splay(int x,int &tar)
{
int fa,u=f[tar];
for(;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u)
rotate(get(fa)==get(x)?fa:x);
tar=x;
}
inline int getl(int x)
{
while(ch[x][0]) x=ch[x][0];
return x;
}
inline int getr(int x)
{
while(ch[x][1]) x=ch[x][1];
return x;
}
inline void insert(int &o,double x,double y,int last)
{
if(!o)
{
o=++cnt;
f[o]=last, X[o]=x,Y[o]=y;
return;
}
insert(ch[o][x-X[o]>eps], x, y, o);
}
inline int getans(int x,double k)
{
if(!x) return 0;
if(k<=lk[x]+eps&&k+eps>=rk[x]) return x;
if(lk[x]<k+eps) return getans(ch[x][0], k);
else return getans(ch[x][1], k);
}
inline void del(int x)
{
if(!ch[x][0])
{
int right=getl(ch[x][1]);
splay(right,ch[x][1]), root=right, f[root]=ch[x][1]=0;
lk[root]=inf;
}
else if(!ch[x][1])
{
int left=getr(ch[x][0]);
splay(left,ch[x][0]), root=left, f[root]=ch[x][0]=0;
rk[root]=-inf;
}
else
{
int left=getr(ch[x][0]),right=getl(ch[x][1]);
splay(left,ch[x][0]), splay(right,ch[x][1]);
root=left, f[root]=0, ch[root][1]=right, f[right]=root;
rk[root]=lk[right]=slope(root,right);
}
}
// 平衡树上查询前驱
inline int pre(int x)
{
int cur=ch[x][0],re=0;
while(cur)
{
if(slope(cur,x)+eps>=rk[cur]) re=cur,cur=ch[cur][0];
else cur=ch[cur][1];
}
return re;
}
// 平衡树上查询后继
inline int nxt(int x)
{
int cur=ch[x][1],re=0;
while(cur)
{
if(slope(x,cur)<=lk[cur]+eps) re=cur,cur=ch[cur][1];
else cur=ch[cur][0];
}
return re;
}
inline void maintain(int x)
{
splay(x,root);
if(ch[root][0])
{
int left=pre(root);
if(left)
{
splay(left, ch[x][0]);
ch[left][1]=f[ch[left][1]]=0;
rk[left]=lk[x]=slope(left, x);
}
else lk[x]=-inf;
}
else lk[x]=inf;
if(ch[x][1])
{
int right=nxt(x);
if(right)
{
splay(right, ch[x][1]);
ch[right][0]=f[ch[right][0]]=0;
rk[x]=lk[right]=slope(x, right);
}
else rk[x]=inf;
}
else rk[x]=-inf;
if(lk[x]-rk[x]<=eps) del(x);
}
}splay;
int n;
ll d;
struct Node
{
ll P,D,G,R;
}t[maxn];
ll F[maxn];
bool cmp(Node i,Node j) { return i.D<j.D; }
inline void work()
{
root=splay.cnt=0;
int i,j=0;
for(i=1;i<=n;++i) scanf("%lld%lld%lld%lld",&t[i].D,&t[i].P,&t[i].R,&t[i].G);
t[++n].D=d+1;
t[n].P=t[n].R=t[n].G=0;
sort(t+1,t+1+n,cmp);
ll ret=F[0], re=0;
for(i=1;i<=n;++i)
{
F[i]=F[i-1];
if(root)
{
j=splay.getans(root, (long double)-1.00000*t[i].D);
j=idxx[j];
re=F[j]-t[j].P+t[j].R+t[j].G*(t[i].D-t[j].D-1LL);
F[i]=max(F[i-1],re);
}
ret=max(ret,F[i]);
if(i!=n&&F[i]>=t[i].P)
{
splay.insert(root, (long double)t[i].G, (long double)(F[i]-t[i].P+t[i].R-t[i].G*(t[i].D+1LL)),0);
idxx[splay.cnt]=i;
splay.maintain(splay.cnt);
}
}
printf("%lld\n",ret);
for(int i=0;i<=splay.cnt;++i) splay.ch[i][0]=splay.ch[i][1]=splay.f[i]=splay.lk[i]=splay.rk[i]=0;
root=splay.cnt=0;
}
int main()
{
for(int cas=1;;++cas)
{
scanf("%d%lld%lld",&n,&F[0],&d);
if(n==0&&F[0]==0&&d==0) break;
printf("Case %d: ",cas);
work();
}
return 0;
}