题面传送门

首先很明显我们会按照 \(d_i\) 的顺序从小到大买这些机器,故不管三七二十一先将所有机器按 \(d_i\) 从小到大排序。

考虑 \(dp\),\(dp_i\) 表示在时刻 \(d_i\) 及以前卖掉手头的机器,最多能剩下多少钱。

转移显然就枚举上一个购买的机器编号 \(j\),即 \(dp_i=\max\limits_{j=1}^{i-1}dp_j-p_j+g_j(d_i-d_j-1)+r_j\),其中 \(j\) 可以转移到 \(i\) 当前仅当 \(dp_j\geq p_j\)。最终答案可以选择在某一时刻卖完某个机器后就不再买入新的机器了,即 \(\max\limits_{i=1}^ndp_i\),也可以选择将某个机器用到 \(D\) 天结束,即 \(\max\limits_{i=1}^ndp_i-p_i+g_i(D-d_i)+r_i(dp_i\ge p_i)\)

这样暴力转移是 \(n^2\) 的,但是有一个很明显的优化是这个 \(dp\) 转移满足斜率优化的 \(f_i=d_i+\max a_ib_j+c_j\) 的形式,故考虑斜率优化。考虑两个决策点 \(j,k\) 满足 \(g_j>g_k\),那么从 \(j\) 转移比从 \(k\) 转移更优当前仅当:

\[\begin{aligned}&dp_j-p_j+g_j(d_i-d_j-1)+r_j>dp_k-p_k+g_k(d_i-d_k-1)+r_k\\\Leftrightarrow\ &dp_j-p_j-g_j(d_j+1)+r_j+g_jd_i>dp_k-p_k-g_k(d_k+1)+r_k+g_kd_i\\\Leftrightarrow\ &(dp_j-p_j-g_j(d_j+1)+r_j)-(dp_k-p_k-g_k(d_k+1)+r_k)>d_i(g_k-g_j)\\\Leftrightarrow\ &\dfrac{(dp_j-p_j-g_j(d_j+1)+r_j)-(dp_k-p_k-g_k(d_k+1)+r_k)}{g_j-g_k}>-d_i\end{aligned}
\]

斜率优化转移一下即可。

由于此题 \(g_i\) 不单调,故考虑 CDQ 分治维护斜率优化,具体来说,假设我们要用 \([l,mid]\) 中点的贡献更新 \(dp_{mid+1},dp_{mid+2},\dots,dp_r\),我们将 \([l,mid]\) 中所有满足要求的决策点按 \(g_i\) 从小到大排个序并依次加入凸壳,查找 \(d_i\) 的贡献时就在凸包上二分第一个斜率大于 \(-d_i\) 的点并转移即可。

还有就是对于 \(g_j=g_k\) 的 \(j,k\),相当于平面上坐标为 \(A(g_j,dp_j-p_j-g_j(d_j+1)+r_j),B(g_k,dp_k-p_k-g_k(d_k+1)+r_k)\) 的两点,那么我们对于横坐标相同的点肯定是先将纵坐标小的加入凸包,再将纵坐标大的加入凸包,因此在排序过程中要按\(g_j\) 为第一关键字,\(dp_j-p_j-g_j(d_j+1)+r_j\) 为第二关键字排序。我因此 WA 了好多好多发,xtbz。

这是萌新第二次写 CDQ 分治维护斜率优化哦,大佬不喜勿喷

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1e5;
const ll INF=0x3f3f3f3f3f3f3f3fll;
int n,c,d,Casen=0;
struct event{
int d,p,r,g,id;
bool operator <(const event &rhs){
return d<rhs.d;
}
} a[MAXN+5],tmp[MAXN+5];
ll dp[MAXN+5];
int q[MAXN+5],tl=0;
double slope(int j,int k){
if(a[j].g==a[k].g) return INF;
return 1.0*((dp[j]-1ll*a[j].d*a[j].g-a[j].g+a[j].r-a[j].p)-(dp[k]-1ll*a[k].d*a[k].g-a[k].g+a[k].r-a[k].p))/(a[j].g-a[k].g);
}
int bsearch(int l,int r,int sl){
if(l==r) return l;int mid=l+r>>1;
if(slope(q[mid],q[mid+1])>sl) return bsearch(mid+1,r,sl);
else return bsearch(l,mid,sl);
}
void cdq(int l,int r){
if(l==r){chkmax(dp[l],dp[l-1]);return;}
int mid=l+r>>1;cdq(l,mid);for(int i=l;i<=mid;i++) tmp[i]=a[i];
sort(tmp+l,tmp+mid+1,[](event lhs,event rhs){
if(lhs.g^rhs.g) return lhs.g<rhs.g;int j=lhs.id,k=rhs.id;
return (dp[j]-1ll*a[j].d*a[j].g-a[j].g+a[j].r-a[j].p)<(dp[k]-1ll*a[k].d*a[k].g-a[k].g+a[k].r-a[k].p);
});
tl=0;
for(int i=l;i<=mid;i++){
if(dp[tmp[i].id]<tmp[i].p) continue;
while(tl&&slope(q[tl],tmp[i].id)>slope(q[tl-1],q[tl])) tl--;
q[++tl]=tmp[i].id;
}
for(int i=mid+1;i<=r;i++){
if(!tl) continue;
int pos=bsearch(1,tl,-a[i].d),id=q[pos];
chkmax(dp[i],dp[id]+1ll*(a[i].d-a[id].d-1)*a[id].g+a[id].r-a[id].p);
// printf("%d %d\n",i,id);
}
cdq(mid+1,r);
}
void solve(){
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&a[i].d,&a[i].p,&a[i].r,&a[i].g);
} sort(a+1,a+n+1);
for(int i=1;i<=n;i++) a[i].id=i;
memset(dp,0,sizeof(dp));
ll ans=c;dp[0]=c;cdq(1,n);
for(int i=1;i<=n;i++) if(dp[i]>=a[i].p)
chkmax(ans,dp[i]+a[i].r+1ll*(d-a[i].d)*a[i].g-a[i].p);
for(int i=1;i<=n;i++) chkmax(ans,dp[i]);
printf("Case %d: %lld\n",++Casen,ans);
}
int main(){
while(~scanf("%d%d%d",&n,&c,&d)){
if(!n||!c||!d) break;solve();
}
return 0;
}

Codeforces Gym 101175F - Machine Works(CDQ 分治维护斜率优化)的更多相关文章

  1. hdu 3842 Machine Works(cdq分治维护凸壳)

    题目链接:hdu 3842 Machine Works 详细题解: HDU 3842 Machine Works cdq分治 斜率优化 细节比较多,好好体会一下. 在维护斜率的时候要考虑x1与x2是否 ...

  2. LOJ 2353 & 洛谷 P4027 [NOI2007]货币兑换(CDQ 分治维护斜率优化)

    题目传送门 纪念一下第一道(?)自己 yy 出来的 NOI 题. 考虑 dp,\(dp[i]\) 表示到第 \(i\) 天最多有多少钱. 那么有 \(dp[i]=\max\{\max\limits_{ ...

  3. [NOI2007]货币兑换 cdq分治,斜率优化

    [NOI2007]货币兑换 LG传送门 妥妥的\(n \log n\)cdq做法. 这题用cdq分治也可以\(n \log n\)但是在洛谷上竟然比一些优秀的splay跑得慢真是见了鬼了看来还是人丑常 ...

  4. [NOI2007]货币兑换 「CDQ分治实现斜率优化」

    首先每次买卖一定是在某天 $k$ 以当时的最大收入买入,再到第 $i$ 天卖出,那么易得方程: $$f_i = \max \{\frac{A_iRate_kf_k}{A_kRate_k + B_k} ...

  5. BZOJ1492: [NOI2007]货币兑换Cash(CDQ分治,斜率优化动态规划)

    Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...

  6. Codeforces 848C Goodbye Souvenir(CDQ 分治)

    题面传送门 考虑记录每个点的前驱 \(pre_x\),显然答案为 \(\sum\limits_{i=l}^{r} i-pre_i (pre_i \geq l)\) 我们建立一个平面直角坐标系,\(x\ ...

  7. 【BZOJ4311】向量(线段树分治,斜率优化)

    [BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...

  8. Codeforces 1093E Intersection of Permutations [CDQ分治]

    洛谷 Codeforces 思路 一开始想到莫队+bitset,发现要T. 再想到分块+bitset,脑子一抽竟然直接开始写了,当然也T了. 最后发现这就是个裸的CDQ分治-- 发现\(a\)不变,可 ...

  9. HDU 3824/ BZOJ 3963 [WF2011]MachineWorks (斜率优化DP+CDQ分治维护凸包)

    题面 BZOJ传送门(中文题面但是权限题) HDU传送门(英文题面) 分析 定义f[i]f[i]f[i]表示在iii时间(离散化之后)卖出手上的机器的最大收益.转移方程式比较好写f[i]=max{f[ ...

随机推荐

  1. 【c++ Prime 学习笔记】第18章 用于大型程序的工具

    大规模应用程序的特殊要求包括: 在独立开发的子系统之间协同处理错误:异常处理 使用各种库(可能包含独立开发的库)进行协同开发:命名空间 对比较复杂的应用概念建模:多重继承 18.1 异常处理 异常处理 ...

  2. centos7 配置ftp服务器搭建(匿名访问,以及本地登录)

    大家好,今天来给大家分享一个基于centos 7的ftp服务器搭建 实现功能:匿名访问,本地登录 查看系统版本: [root@localhost ~]# cat /etc/redhat-release ...

  3. Beta实际开发与初始计划的比较

    零.说明 本篇博客为Beta阶段开始十天后,实际开发工作与初始计划的比较 截止至本篇博客发布为止,团队所有成员已完成计网考试,将在本周日进行充分的接口测试 一.比较 1.与初始计划对比 初始计划 实际 ...

  4. Unity 制作不规则形状button

    在游戏开发中,我们有时需要制作不规则形状的按键. Unity3d中使用UGUI的Button控件只能实现规则的长方形按钮.而通过给Button的Image组件添加对应的贴图(sprite)我们可以实现 ...

  5. Spring 5 中函数式web开发中的swagger文档

    Spring 5 中一个非常重要的更新就是增加了响应式web开发WebFlux,并且推荐使用函数式风格(RouterFunction和 HandlerFunction)来开发WebFlux.对于之前主 ...

  6. js基础学习之"=="与"==="的区别

    var a = 1; var b = 1; var c = "1"; 1. "==" 可理解为相等运算符.相等运算符比较时,会自己进行类型转换,等于什么类型就会 ...

  7. Kubernetes集群环境搭建全过程

    资源准备以及服务器初始化 所有服务器执行一下脚本进行配置信息初始化: #!/bin/bash cd `dirname $0` # 关闭selinux setenforce 0 sed -i '/SEL ...

  8. 一套比较好用的公众号UI框架-weui

    最近工作原因 需要在pd端弄一套js类似bootstrap框架 由于使用环境是在公众号终端用的比较多! 类似上面这样的样式 所以我从微信官方开始找起 最后找到了WEUI 还别说 真的挺好用的 这是大佬 ...

  9. windows下wchar_t的问题

    使用vs新建工程或者编译工程的时候默认在编译设置里面讲wchar_t设置为内置类型,如下图: 但是在编译相互依赖的工程的时候,如果有的工程不将wchar_t设置为内置类型的时候,将会出现链接错误,需要 ...

  10. GEOS使用记录

    由于需要计算GIS障碍物的缓冲区,所以研究了 一下GEOS库的使用,将使用的一些细节内容记录一下: 1.vs2010IDE无法编译较高版本的GEOS库,较高版本的库使用了更加高级的C++语法,如果想使 ...