@description@

给定若干个三维空间的点 (xi, yi, zi),求一个坐标都为整数的点 P,使得 P 到这些点的最大曼哈顿距离最小。

原题传送门。

@solution@

显然三分套三分套三分。

看到最大值,把绝对值 |x| 拆成 max(x, -x)。接着二分最大距离 d,则 max(...) ≤ d。

因此得到如下不等式组:

\[\begin{cases}
l_1 \leq x + y + z \leq r_1 \\
l_2 \leq x + y - z \leq r_2 \\
l_3 \leq x - y + z \leq r_3 \\
l_4 \leq - x + y + z \leq r_4 \\
\end{cases}
\]

仿照二维情况将曼哈顿距离转切比雪夫距离的方式,作代换 \(a = x + y - z, b = x - y + z, c = - x + y + z\)。

则有:\(x = \frac{a + b}{2}, y = \frac{a + c}{2}, z = \frac{b + c}{2}, x + y + z = a + b + c\)。

当 \(x, y, z\) 都是整数时,\(a, b, c\) 同奇同偶。不妨先枚举奇偶性,则可把原不等式变形为如下形式:

\[\begin{cases}
l_1' \leq a' + b' + c' \leq r_1' \\
l_2' \leq a' \leq r_2' \\
l_3' \leq b' \leq r_3' \\
l_4' \leq c' \leq r_4' \\
\end{cases}
\]

这样做的好处是,我们只留下了一个 \(a', b', c'\) 互相制约的不等式。

剩下的只需要贪心地把 \(a', b', c'\) 先设置为最小值,然后往上调整即可。时间复杂度 \(O(n\log A)\)。

@accepted code@

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std; typedef long long ll; const ll INF = ll(3E18);
const int dx[4] = {1, 1, 1, -1};
const int dy[4] = {1, 1, -1, 1};
const int dz[4] = {1, -1, 1, 1}; ll le[4], ri[4];
ll a1, b1, c1;
bool get() {
for(int i=0;i<4;i++)
if( le[i] > ri[i] ) return false; a1 = le[1], b1 = le[2], c1 = le[3];
if( a1 + b1 + c1 > ri[0] ) return false;
else {
if( a1 + b1 + c1 < le[0] ) {
if( ri[1] + b1 + c1 >= le[0] ) {
a1 = le[0] - b1 - c1;
return true;
} else {
a1 = ri[1];
if( a1 + ri[2] + c1 >= le[0] ) {
b1 = le[0] - a1 - c1;
return true;
} else {
b1 = ri[2];
if( a1 + b1 + ri[3] >= le[0] ) {
c1 = le[0] - a1 - b1;
return true;
} else return false;
}
}
} else return true;
}
} ll lb[4], ub[4];
ll ansx, ansy, ansz;
bool check(ll d) {
for(int o=0;o<=1;o++) {
le[0] = (lb[0] - d) - 3*o, ri[0] = (ub[0] + d) - 3*o;
for(int i=1;i<4;i++) le[i] = (lb[i] - d) - o, ri[i] = (ub[i] + d) - o;
for(int i=0;i<4;i++) le[i] = ceil((long double)le[i] / 2), ri[i] = floor((long double)ri[i] / 2);
if( get() ) {
ll a = 2*a1 + o, b = 2*b1 + o, c = 2*c1 + o;
ansx = (a + b) / 2, ansy = (a + c) / 2, ansz = (b + c) / 2;
return true;
}
}
return false;
}
void solve() {
int n; scanf("%d", &n);
for(int i=0;i<4;i++) lb[i] = -INF, ub[i] = INF;
for(int i=1;i<=n;i++) {
ll x, y, z; scanf("%lld%lld%lld", &x, &y, &z);
for(int j=0;j<4;j++) {
lb[j] = max(lb[j], dx[j]*x + dy[j]*y + dz[j]*z);
ub[j] = min(ub[j], dx[j]*x + dy[j]*y + dz[j]*z);
}
} ll l = 0, r = INF;
while( l < r ) {
ll m = (l + r) >> 1;
if( check(m) ) r = m;
else l = m + 1;
}
check(r); printf("%lld %lld %lld\n", ansx, ansy, ansz);
} int main() {
int T; scanf("%d", &T);
while( T-- ) solve();
}

@details@

一开始本来想转类切比雪夫距离结果发现好像二维三维不一样。

然后尝试从立体几何入手想象,发现我完全没学过立几。

果然这是一道数学题啊。数学题好难。

@codeforces - 685C@ Optimal Point的更多相关文章

  1. Codeforces 685C - Optimal Point(分类讨论+乱搞)

    Codeforces 题面传送门 & 洛谷题面传送门 分类讨论神题. 首先看到最大值最小,一眼二分答案,于是问题转化为判定性问题,即是否 \(\exists x_0,y_0,z_0\) 满足 ...

  2. [Codeforces 1214A]Optimal Currency Exchange(贪心)

    [Codeforces 1214A]Optimal Currency Exchange(贪心) 题面 题面较长,略 分析 这个A题稍微有点思维难度,比赛的时候被孙了一下 贪心的思路是,我们换面值越小的 ...

  3. 【模拟】Codeforces 710B Optimal Point on a Line

    题目链接: http://codeforces.com/problemset/problem/710/B 题目大意: 给N个点的坐标,在X轴上找到最靠左的点使得这个点到N个点距离之和最小. 题目思路: ...

  4. CodeForces 710B Optimal Point on a Line (数学,求中位数)

    题意:给定n个坐标,问你所有点离哪个近距离和最短. 析:中位数啊,很明显. 代码如下: #pragma comment(linker, "/STACK:1024000000,10240000 ...

  5. codeforces 622C. Optimal Number Permutation 构造

    题目链接 假设始终可以找到一种状态使得值为0, 那么两个1之间需要隔n-2个数, 两个2之间需要隔n-3个数, 两个3之间隔n-4个数. 我们发现两个三可以放到两个1之间, 同理两个5放到两个3之间. ...

  6. CodeForces 710B Optimal Point on a Line

    递推. 先对$a[i]$进行从小到大排序. 然后计算出每个点左边所有点到这个点的距离之和$L[i]$,以及右边每个点到这个点的距离之和$R[i]$. 这两个都可以递推得到. $L\left[ i \r ...

  7. CodeForces 622D Optimal Number Permutation

    是一个简单构造题. 请观察公式: 绝对值里面的就是 |di-(n-i)|,即di与(n-i)的差值的绝对值. 事实上,对于任何n,我们都可以构造出来每一个i的di与(n-i)的差值为0. 换句话说,就 ...

  8. Codeforces 1262D Optimal Subsequences(BIT+二分)

    首先比较容易想到肯定是前k大的元素,那么我们可以先对其进行sort,如果数值一样返回下标小的(见题意),接下里处理的时候我们发现需要将一个元素下标插入到有序序列并且需要访问第几个元素是什么,那么我们可 ...

  9. codeforces 1262D Optimal Subsequences 主席树询问第k小

    题意 给定长度为\(n\)的序列\(a\),以及m个询问\(<k,pos>\),每次询问满足下列条件的子序列中第\(pos\)位的值为多少. 子序列长度为\(k\) 序列和是所有长度为\( ...

随机推荐

  1. Django中的事务与ajax

    一 事务与锁 1.行级锁 行级锁是由存储引擎实现的.如mysql里默认指定的InnoDB存储引擎,由它实现行级锁.InnoDB的行级锁定同样分为两种类型,共享锁(X)和排他锁(S). 对于UPDATE ...

  2. es6的数组操作

    //foreach 迭代 var arr = [1, 2, 3]; var sum = 0; arr.forEach(function(value, index, array) { console.l ...

  3. indetityserver4-implicit-grant-types-请求流程叙述-下篇

    上一篇将请求流程描述一遍,这篇将描述一下相关的源码. 1 访问客户端受保护的资源 GET /Home/Secure HTTP/1.1HTTP/1.1 302 Found Date: Tue, 23 O ...

  4. DataFrame迭代过程中多行修改

    方法1:df.loc[conditions]=row.values,逐行地进行整行替换 for row in df.iterrows(): row['given_amount']=row['amoun ...

  5. 离散的差分进化Discrete DE

    一般的差分算法的变异规则:Xmutation=Xr1+F(Xr2-Xr3),F为缩放因子, 离散差分进化DDE的变异规则:设每个解为K个元素的集合,则Xr2-Xr3:求出Xr2与Xr3有m个共同元素, ...

  6. Spring IoC componet-scan 节点解析详解

    前言 我们在了解 Spring 容器的扩展功能 (ApplicationContext) 之前,先介绍下 context:componet-scan 标签的解析过程,其作用很大是注解能生效的关键所在. ...

  7. js 获取当前日期时间

    function getCurrentDate(fulldate = false, separator = ['-', ':']) { let currentTimeObj = new Date(); ...

  8. 前端代码高亮显示解决方案: prism

    目录 1. 场景描述 2. React Prism 2.1 prismjs 库 2.2 babel-plugin-prismjs 插件 3. demo 4. 注意点 5. 参考链接 1. 场景描述 在 ...

  9. Redis 入门到分布式 (五) Redis持久化的取舍和选择

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) Redis持久化的取舍和选择 持久化的作用 RDB AOF RDB和AOF的选择 一.持久化的作用   ...

  10. Java实现 LeetCode 1111 有效括号的嵌套深度(阅读理解题,位运算)

    1111. 有效括号的嵌套深度 有效括号字符串 定义:对于每个左括号,都能找到与之对应的右括号,反之亦然.详情参见题末「有效括号字符串」部分. 嵌套深度 depth 定义:即有效括号字符串嵌套的层数, ...