\(\mathcal{Description}\)

  Link.

  给定你初始拥有的钱数 \(C\) 以及 \(N\) 台机器的属性,第 \(i\) 台有属性 \((d_i,p_i,r_i,g_i)\),分别是出售时间、售价、转卖价、单日工作收益。机器在买入或转卖当天不提供收益,且你同一时刻最多拥有一台机器,在 \((D+1)\) 天时必须转卖拥有的机器。求第 \((D+1)\) 天你拥有的最大钱数。\(n\le10^5\)。

\(\mathcal{Solution}\)

  比较自然的想法时依时间顺序 DP,所以先将机器按时间排序。令 \(f(i)\) 表示在 \(d_i\) 时刻,卖掉手里的机器后拥有的最大钱数,添加一台虚拟机器 \((D+1,0,0,0)\) 用于收集答案。考虑转移:

\[f(i)=\max_{f(j)\ge p_j}\{f(j)-p_j+r_j+g_j(d_i-d_j-1)\}.
\]

注意同一天多次买卖机器显然不优,所以 \(g_j\) 的系数不需要对 \(0\) 取 \(\max\)。这个一看就是斜优的样子,研究 \(f(u),f(v)\) 对 \(i\) 的转移:

\[\begin{aligned}
&f(u)-p_u+r_u+g_u(d_i-d_u-1)>f(v)-p_v+r_v+g_v(d_i-d_v-1) \\
\Longleftrightarrow~~~~&[f(u)-p_u+r_u-g_u(d_u+1)]-[f(v)-p_v-r_v-g_v(d_v+1)]>(g_v-g_u)d_i \\
\Longleftrightarrow~~~~&\frac{h(u)-h(v)}{g_u-g_v}<-d_i~~~~(g_u<g_v).
\end{aligned}
\]

  很遗憾我们需要 \(g_u<g_v\) 控制符号,所以无法保证此时斜率 \(-d_i\) 的单调性,所以得写一发 CDQ 或者李超树。复杂度都是 \(\mathcal O(n\log n)\)。

\(\mathcal{Code}\)

/*+Rainybunny+*/

#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i) typedef long long LL;
typedef long double LD; inline void chkmax(LL& u, const LL v) { u < v && (u = v); } const int MAXN = 1e5;
int N, C, D;
LL f[MAXN + 5], g[MAXN + 5];
struct Machine { int day, buy, sel, pro; } mch[MAXN + 5]; inline LD slope(const int u, const int v) {
return LD(g[u] - g[v]) / (mch[u].pro - mch[v].pro);
} inline std::vector<int> solve(const int l, const int r) {
if (l == r) {
chkmax(f[l], C);
g[l] = f[l] - mch[l].buy + mch[l].sel
- mch[l].pro * (mch[l].day + 1ll);
// printf("f(%d)=%lld\n", l, f[l]);
return f[l] >= mch[l].buy ? std::vector<int>{ l } : std::vector<int>{};
} int mid = l + r >> 1;
auto&& cvxL(solve(l, mid));
for (int i = 0, j = mid + 1; j <= r; ++j) {
while (i + 1 < int(cvxL.size())
&& slope(cvxL[i], cvxL[i + 1]) >= -mch[j].day) ++i;
if (i < int(cvxL.size())) { // maybe cvxL is empty.
int p = cvxL[i];
chkmax(f[j], f[p] - mch[p].buy + mch[p].sel
+ mch[p].pro * (mch[j].day - mch[p].day - 1ll));
}
}
auto&& cvxR(solve(mid + 1, r)); std::vector<int> ret;
auto push = [&](const int u) { // maintain the up-convex.
while (ret.size() > 1 && slope(ret[ret.size() - 2], ret.back())
<= slope(ret.back(), u)) ret.pop_back();
ret.push_back(u);
}; for (size_t i = 0, j = 0; i < cvxL.size() || j < cvxR.size();) {
if (i < cvxL.size() && j < cvxR.size()
&& mch[cvxL[i]].pro == mch[cvxR[j]].pro) {
++(g[cvxL[i]] < g[cvxR[j]] ? i : j); // pass the smaller one.
} else if (j == cvxR.size()
|| (i < cvxL.size() && mch[cvxL[i]].pro < mch[cvxR[j]].pro)) {
push(cvxL[i++]);
} else {
push(cvxR[j++]);
}
}
return ret;
} int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); while (std::cin >> N >> C >> D && N | C | D) {
rep (i, 1, N) {
std::cin >> mch[i].day >> mch[i].buy >> mch[i].sel >> mch[i].pro;
}
std::sort(mch + 1, mch + N + 1,
[](const Machine& u, const Machine& v) { return u.day < v.day; });
mch[++N] = { D + 1, 0, 0, 0 };
rep (i, 1, N) f[i] = g[i] = 0; solve(1, N);
static int cas = 0;
std::cout << "Case " << ++cas << ": " << f[N] << '\n';
} return 0;
}

Solution -「WF2011」「BZOJ #3963」MachineWorks的更多相关文章

  1. 「BZOJ 4228」Tibbar的后花园

    「BZOJ 4228」Tibbar的后花园 Please contact lydsy2012@163.com! 警告 解题思路 可以证明最终的图中所有点的度数都 \(< 3\) ,且不存在环长是 ...

  2. 「BZOJ 3645」小朋友与二叉树

    「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...

  3. 「BZOJ 4502」串

    「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...

  4. 「BZOJ 4289」 PA2012 Tax

    「BZOJ 4289」 PA2012 Tax 题目描述 给出一个 \(N\) 个点 \(M\) 条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点 \(1\) 到点 \( ...

  5. 「BZOJ 2534」 L - gap字符串

    「BZOJ 2534」 L - gap字符串 题目描述 有一种形如 \(uv u\) 形式的字符串,其中 \(u\) 是非空字符串,且 \(v\) 的长度正好为 \(L\), 那么称这个字符串为 \( ...

  6. 「BZOJ 2956」模积和

    「BZOJ 2956」模积和 令 \(l=\min(n,m)\).这个 \(i\neq j\) 非常不优雅,所以我们考虑分开计算,即: \[\begin{aligned} &\sum_{i=1 ...

  7. Solution -「CTS 2019」「洛谷 P5404」氪金手游

    \(\mathcal{Description}\)   Link.   有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...

  8. 「雅礼集训 2018 Day2」农民

    传送门 Description  「搞 OI 不如种田.」 小 D 在家种了一棵二叉树,第 ii 个结点的权值为 \(a_i\). 小 D 为自己种的树买了肥料,每天给树施肥. 可是几天后,小 D 却 ...

  9. 「题解」「美团 CodeM 资格赛」跳格子

    目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...

随机推荐

  1. Centos7 暂时记录

    chown 修改属主和属组信息 chown -R 对目录所有子的子目录和文件进行修改属主信息 w命令 USER TTY FROM    LOGIN@ IDLE JCPU PCPU WHATroot   ...

  2. 用Less 的 js方式替代 bootStrap 里 [class*=”span”]

    Bootstrap 里的 grid system 里面 (源代码) 有这么一段, [class*="span"] { float: left; margin-left: @grid ...

  3. Three.js 实现虎年春节3D创意页面

    背景 虎年 春节将至,本文使用 React + Three.js 技术栈,实现趣味 3D 创意页面.本文包含的知识点主要包括:ShadowMaterial. MeshPhongMaterial 两种基 ...

  4. Linux基础之终端、控制台、tty、pty简介说明

    最近在搞Linux提权的时候,有时候su 用户名 登录的时候发现登录不了,因为tty终端,交互不了,所以我也来总结一下 一. 基本概念 1. ttytty(终端设备的统称):tty一词源于telety ...

  5. ADO.NET数据访问基础与综合应用2020年10月31日20:17:09学习笔记

    四.创建数据表 1.数据表的名称. 2.表中的字段名.数据类型.是否可以为空.字段的约束.必备的字段(通常会有一个ID,表示实体的唯一性:可以直接手写,也可以使用种子标识自动生成,给定起始值,给定增长 ...

  6. Flink 非对齐Unaligned的checkpoint(源码分析)

    本文源码基于flink1.14 在帮助用户排查任务的时候,经常会发现部分task处理的慢,在Exactly once语义时需要等待快照的对齐而白白柱塞的情况 在flink1.11版本引入了非对齐的ch ...

  7. nRF24L01基于FIFO TX队列的发送性能优化

    RF24项目代码分析 头文件 https://github.com/nRF24/RF24/blob/master/RF24.h 源文件 https://github.com/nRF24/RF24/bl ...

  8. java之类的抽取与对象的创建

    Java语言之类的抽取 前言:世界由什么组成?This is a question.有人说是原子.分子,有人说是山川草木. 诚然,一千个人眼中有一千个哈姆雷特.而在程序员眼中,万物皆对象. 定义: 在 ...

  9. 【记录一个问题】macos下使用opencl, clSetEventCallback不生效

    一开始的调用顺序是这样: enqueueWriteBuffer enqueueNDRangeKernel enqueueReadBuffer SetEventCallback 执行后主程序用getch ...

  10. zabbix安装 报错 socket '/var/lib/mysql/mysql.sock' (13)]

    安装界面提示: Error connecting to database: Can't connect to local MySQL server through socket '/var/lib/m ...