QOJ1870 Command and Conquer: Red Alert 2

QOJ1870 Command and Conquer: Red Alert 2

你位于一个三维空间内,初始坐标 \((-10^{100},-10^{100},-10^{100})\)。每一步可以从 \((x,y,z)\) 走到 \((x+1,y,z)\) 或 \((x,y+1,z)\) 或 \((x,y,z+1)\),终点为 \((10^{100},10^{100},10^{100})\)。

现有 \(n\) 个任务,第 \(i\) 个任务坐标为 \((x_i,y_i,z_i)\)。你需要确定一个非负整数 \(k\),则位于 \((x,y,z)\) 时可以完成任务 \(i\) 当且仅当 \(\max(|x-x_i|,|y-y_i|,|z-z_i|)\le k\)。

求最小的 \(k\) 使得你可以完成所有任务。

多测,\(\sum n\le2\times10^6\),\(|x_i|,|y_i|,|z_i|\le10^9\),10 秒,512 MB。

解法一

认为 \((x,y,z)\) 可以完成任务 \(i\) 的充要条件为 \(x_i\in[x,x+2k]\land y_i\in[y,y+2k]\land z_i\in[z,z+2k]\),显然不会影响答案。不妨转为求 \(k'=2k\) 的最小值,则 \(k_{\min}=\lceil\frac{k'}{2}\rceil\)。

我们可以贪心走到 \((x_{\min},y_{\min},z_{\min})\) 作为初始位置。

考虑求出 \(x_a\) 取得最小的 \(a\),同理得到 \(y_b\) 最小的 \(b\) 和 \(z_c\) 最小的 \(c\)。此时一定要完成任务 \(a,b,c\) 其中之一。

记 \(f(x)\) 为完成任务 \(x\) 所需的最小 \(k'\)。则 \(f(a)=\max(y_a-y_b,z_a-z_c)\),同理可以计算 \(f(b),f(c)\)。

\(k'\) 可以由每一轮的 \(f\) 取 \(\max\) 得到,因此我们希望 \(f\) 尽可能小,取 \(f(a),f(b),f(c)\) 中最小的点,并且完成这个任务。将这个点删去,此时可以找到新的 \((x_{\min},y_{\min},z_{\min})\) 与 \(a,b,c\),持续操作 \(n\) 轮即可。

用 std::set 模拟上述过程,复杂度 \(O(n\log n)\)。代码。

解法二

二分答案 \(k\)。则此时每个任务形成一个正方体,在正方体内才能完成它。

对于任务 \(i,j\),先 \(i\) 后 \(j\) 的顺序必须满足 \(x_i-k\le x_j+k\land y_i-k\le y_j+k\land z_i-k\le z_j+k\)。如果满足这个条件,则连边 \(i\to j\)。则答案 \(k\) 合法当且仅当图是一个 DAG,即存在一组拓扑序。

直接建图然后拓扑排序是 \(O(n^2\log V)\),无法通过。

考察图的形态,对于零入度点 \(u\),根据条件列出不等式,整理得 \(\max(x_u-x_{\min},y_u-y_{\min},z_u-z_{\min})\le2k\),其中 \(\min\) 为图上未遍历节点的坐标最小值。

可以直接维护剩余点三个维度的最小值。用 set 维护带一个 \(\log\) 比较危险,考虑队列模拟 set。

我们将所有点按照 \(x_i,y_i,z_i\) 分别排序,维护六个指针,用于动态更新 \(\min\) 和将节点入队,模拟拓扑过程即可,复杂度 \(O(n\log V)\)。代码。

posted @ 2026-10-25 15:18  stripe_python  阅读(7)  评论(1)    收藏  举报