\(\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. vue 因为使用scope后选择器和标签出现[data-v

    使用scope的以后出现datd-v,例如: <div data-v-2311c06a class="button-warp"> <button data-v-2 ...

  2. Azure Terraform(九)利用 Azure DevOps Pipeline 的审批来控制流程发布

    一,引言 Azure Pipeline 管道是一个自动化过程:但是往往我们由于某种原因,需要在多个阶段之前获得批准之后再继续下一步流程,所以我们可以向Azure Pipeline 管道添加审批!批准流 ...

  3. 园子的推广博文:欢迎收看 Apache Flink 技术峰会 FFA 2021 的视频回放

    园子专属收看链接:https://developer.aliyun.com/special/ffa2021/live#?utm_content=g_1000316459 Flink Forward 是 ...

  4. 小白也能看懂的Redis教学基础篇——做一个时间窗限流就是这么简单

    不知道ZSet(有序集合)的看官们,可以翻阅我的上一篇文章: 小白也能看懂的REDIS教学基础篇--朋友面试被SKIPLIST跳跃表拦住了 书接上回,话说我朋友小A童鞋,终于面世通过加入了一家公司.这 ...

  5. 【记录一个问题】golang中使用sync.Pool反而造成了负优化

    之前有这样的代码:从http收数据后,进行snappy解码: dst := make([]byte, 0, len(httpRequestData)*5) dst, err = snappy.Deco ...

  6. 分享一个学习cesiumjs的中文社区

    在cesiumjs中文社区的时间线中我写到: 2018年10月10日 注册用户数51,日uv破100 Mark截图 2018年06月22日 上线测试 2018年06月19日 获得cesiumcn.or ...

  7. 【转载】Systemd 入门教程:实战篇

    作者: 阮一峰 日期: 2016年3月 8日 上一篇文章,我介绍了 Systemd 的主要命令,今天介绍如何使用它完成一些基本的任务. 一.开机启动 对于那些支持 Systemd 的软件,安装的时候, ...

  8. linux下查看 SELinux状态及关闭SELinux

    SELinux全称为安全增强式 Security-Enhanced Linux(SELinux),是一个在内核中实践的强制存取控制(MAC)安全性机制.SELinux 首先在 CentOS 4 出现, ...

  9. Ubuntu 配置数据库开发环境(mysql oracle mssqlserver sybase)

    1.mysql sudo apt-get install libmysql++-dev //mysql连接库 2.ms sql server/sybase ./configure --prefix=/ ...

  10. 女朋友让我深夜十二点催她睡觉,我有Python我就不干

    事情是这样的:今天晚上,女朋友让我十二点催她睡觉. 不过,可是我实在太困了,熬不下去-- 是吧?女朋友哪有睡觉重要? 但,女朋友的命令,我是不敢违抗的-- 但是睡觉也不能缺! 这时候我们该怎么办呢?是 ...