按卖出时间排序后,设f[i]为买下第i台机器后的当前最大收益,则显然有f[i]=max{f[j]+gj*(di-dj-1)+rj-pi},且若此值<0,应设为-inf以表示无法购买第i台机器。

  考虑优化,显然是一个斜率优化式子,设j转移优于k,则f[j]+gj(di-dj-1)+rj>f[k]+gk(di-dk-1)+rk,移项得(f[j]-gjdj-gj+rj)-(f[k]-gkdk-gk+rk)>di(gk-gj)。g没有单调性,于是cdq分治,按g排序建上凸壳即可。

  注意比较斜率时只能用long double,因为乘法会溢出。对于横坐标相同的点需要特判一下,如果加进去的点纵坐标较大就把之前的点弹掉。感觉每次写斜率优化对这种问题都毫无办法。复杂度O(nlogn)。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 100010
#define inf 2000000000000000000ll
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,m,k,q[N];
struct data
{
int d,p,r,g,i;ll ans;
bool operator <(const data&a) const
{
return d<a.d;
}
}a[N],b[N];
ll calc(int i){return a[i].ans-1ll*a[i].g*(a[i].d+)+a[i].r;}
bool check(int x,int y,int i)
{
if (a[i].g==a[y].g) return calc(i)>=calc(y);
return (long double)(calc(i)-calc(y))/(a[i].g-a[y].g)>=(long double)(calc(y)-calc(x))/(a[y].g-a[x].g);
}
void solve(int l,int r)
{
if (l>=r) return;
int mid=l+r>>;
solve(l,mid);
int head=,tail=;
for (int i=l;i<=mid;i++)
{
while (tail>&&check(q[tail-],q[tail],i)) tail--;
q[++tail]=i;
}
for (int i=mid+;i<=r;i++)
{
while (head<tail&&calc(q[head+])-calc(q[head])>-1ll*a[i].d*(a[q[head+]].g-a[q[head]].g)) head++;
if (calc(q[head])+1ll*a[q[head]].g*a[i].d-a[i].p>=)
a[i].ans=max(a[i].ans,calc(q[head])+1ll*a[q[head]].g*a[i].d-a[i].p);
}
solve(mid+,r);
int i=l,j=mid+;
for (int k=l;k<=r;k++)
if (i<=mid&&a[i].g<a[j].g||j>r) b[k]=a[i++];
else b[k]=a[j++];
for (int k=l;k<=r;k++) a[k]=b[k];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3963.in","r",stdin);
freopen("bzoj3963.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),k=read();
while (n)
{
for (int i=;i<=n;i++) a[i].d=read(),a[i].p=read(),a[i].r=read(),a[i].g=read(),a[i].i=i;
n++,a[n].d=k+,a[n].p=a[n].r=a[n].g=;
sort(a+,a+n+);
for (int i=;i<=n;i++) a[i].ans=-inf;a[].ans=m;
solve(,n);
for (int i=;i<=n;i++) a[].ans=max(a[].ans,a[i].ans);
printf("Case ");printf("%d",++T);printf(": ");printf(LL,a[].ans);
n=read(),m=read(),k=read();
}
return ;
}

最新文章

  1. chrome浏览器限制的端口
  2. Qt之Qprocess
  3. Zookeeper 监视(Watches) 简介(转)
  4. 初学JDBC,防SQL注入简单示例
  5. WGS84坐标系下,经纬度如何换算成米
  6. IOS7 隐藏状态栏
  7. A9两款芯片管脚数目
  8. Static Classes and Static Class Members
  9. 理解JS中的call、apply、bind方法(*****************************************************************)
  10. netty之NioEventLoopGroup源码分析二
  11. The connection to the server localhost:8080 was refused - did you specify the right host or port?
  12. Java开发笔记(六十七)清单:ArrayList和LinkedList
  13. centos下 telnet访问百度
  14. python并发编程基础之守护进程、队列、锁
  15. centos7.4重置root密码
  16. ☆ [NOIp2016] 天天爱跑步 「树上差分」
  17. js中defer实现等文档加载完在执行脚本
  18. jenkins--使用命令行自动启动Jenkins的job
  19. 【Eclipse】Eclipse中打开cmd窗口和terminal窗口
  20. Rpgmakermv(15) PH任务插件

热门文章

  1. java Arrays数组
  2. 洛谷 P2256 一中校运会之百米跑
  3. SkylineGlobe 6.5 如何实现简单多边形的动态绘制 C#示例代码
  4. 如何修改Oracle服务IP地址
  5. java算法----排序----(5)归并排序
  6. UOJ347 WC2018 通道 边分治、虚树
  7. Java 面试题 == 和 equals 的区别
  8. ASP.NET Core 2.1 源码学习之 Options[2]:IOptions
  9. 【APIO2016】烟火表演
  10. 校内模拟赛 SovietPower Play With Amstar