\(\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. windows下过安全狗

    最近想着把过waf相关的整理一下,本次主要以安全狗4.0为例进行演示 准备工作 安全狗官网:http://free.safedog.cn/install_desc_website.html环境:Win ...

  2. Spring系列2:Spring容器基本概念和使用

    本文内容 简单回顾IoC和DI概念 Spring容器的概念 的xml配置和初始化 容器的基本使用 bean的定义和初始化配置 简单理解IoC和DI概念 什么是IoC控制反转? 通俗地但不严谨地讲,以前 ...

  3. 《剑指offer》面试题31. 栈的压入、弹出序列

    问题描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2 ...

  4. 详解__int128

    前言 如果遇到 long long 开不下的情况,可以使用 __int128 来博一把! note :__int128 仅 \(64\) 位 \(GCC G++\) 支持,不在 \(C++\) 标准中 ...

  5. tomcat容器启动失败疑难问题解决方案

    严重: 子容器启动失败java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: 初始化组件[or ...

  6. Android Studio如何查看自己设计的数据库

    首先点击左上角进入Device File Explorer 进入后 点击data-data 找到你的项目名称 进入后点击你建立的数据库 一步步按照提示进行操作,即可显示你的表

  7. 计算机开放电子书 2021 RC2

    下载方式 pip install CDNDrive # 或 # pip install git+https://github.com/apachecn/CDNDrive cdrive download ...

  8. 【第十二期】腾讯后台实习初试、复试、HR面经 (许愿OC)

    楼主投的很晚属于正常批才开始,初试面试官比较重基础,复试面试官比较看综合能力,HR小姐姐声音好听,腾讯面试官都特别nice! 一面: 看你项目很多,你挨个给我介绍一遍吧 我:一大堆按着简历介绍 日志文 ...

  9. JOISC 2017

    Day1 「JOISC 2017 Day 1」开荒者 首先观察部分分发现分档很多,于是考虑一步步思考上来. 首先有一点关键观察(一): 风吹的顺序是无所谓的,令分别往东.西.南.北吹了 \(r, l, ...

  10. Xcode 官方下载地址 https://developer.apple.com/downloads/

    Xcode 官方下载地址 https://developer.apple.com/downloads/