博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3963 WF2011MachineWorks(动态规划+斜率优化+cdq分治)
阅读量:4965 次
发布时间:2019-06-12

本文共 2312 字,大约阅读时间需要 7 分钟。

  按卖出时间排序后,设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
#include
#include
#include
#include
#include
using namespace std;#define ll long long#define N 100010#define inf 2000000000000000000llchar getc(){ char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}int gcd(int n,int m){ return m==0?n:gcd(m,n%m);}int read(){ int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') { if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),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
=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>>1; solve(l,mid); int head=1,tail=0; for (int i=l;i<=mid;i++) { while (tail>1&&check(q[tail-1],q[tail],i)) tail--; q[++tail]=i; } for (int i=mid+1;i<=r;i++) { while (head
-1ll*a[i].d*(a[q[head+1]].g-a[q[head]].g)) head++; if (calc(q[head])+1ll*a[q[head]].g*a[i].d-a[i].p>=0) a[i].ans=max(a[i].ans,calc(q[head])+1ll*a[q[head]].g*a[i].d-a[i].p); } solve(mid+1,r); int i=l,j=mid+1; for (int k=l;k<=r;k++) if (i<=mid&&a[i].g
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=1;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+1,a[n].p=a[n].r=a[n].g=0; sort(a+1,a+n+1); for (int i=1;i<=n;i++) a[i].ans=-inf;a[0].ans=m; solve(0,n); for (int i=1;i<=n;i++) a[0].ans=max(a[0].ans,a[i].ans); printf("Case ");printf("%d",++T);printf(": ");printf(LL,a[0].ans); n=read(),m=read(),k=read(); } return 0;}

 

转载于:https://www.cnblogs.com/Gloid/p/10269853.html

你可能感兴趣的文章
SELECT LOCK IN SHARE MODE and FOR UPDATE
查看>>
Perl/Nagios – Can’t locate utils.pm in @INC
查看>>
目录导航「深入浅出ASP.NET Core系列」
查看>>
简易爬虫(爬取本地数据)
查看>>
python 进程间通信
查看>>
深拷贝 vs 浅拷贝 释放多次
查看>>
Javascript 有用参考函数
查看>>
点群的判别(三)
查看>>
GNSS 使用DFT算法 能量损耗仿真
查看>>
【转】Simulink模型架构指导
查看>>
MYSQL数据库的导出的几种方法
查看>>
SQL Server-5种常见的约束
查看>>
硬件之美
查看>>
[转载]java开发中的23种设计模式
查看>>
表格的拖拽功能
查看>>
函数的形参和实参
查看>>
文字过长 用 ... 表示 CSS实现单行、多行文本溢出显示省略号
查看>>
1Caesar加密
查看>>
【TP SRM 703 div2 500】 GCDGraph
查看>>
MapReduce 重要组件——Recordreader组件 [转]
查看>>