CF491B New York Hotel 题解
题意:
New York 是个由 $N$ 条垂直道路 (编号为 $1\sim N$) 和 $M$ 条水平道路 (编号为 $1\sim M$ ) 组成的城市。
$C$ 个朋友分别住在该城市中的 $C$ 个酒店中,这些酒店分别坐落在垂直道路和水平道路的相交处。由于他们要庆祝 cxy 的生日,于是他们想去 $H$ 个餐馆中的一个 (当然,这 $H$ 个餐厅也坐落在垂直道路和水平道路的相交处)。
他们想知道,这 $C$ 个酒店到餐馆的最大距离 (即最远的酒店到餐厅的距离) 的最小可能值是多少。帮助朋友们确定一个合适的餐厅以庆祝生日。
假设相邻两个相交处的距离均等于 $1$。
输入格式:
第一行包含两个正整数 $N,M ~(N,M\le 10^9)$ ,描述城市的大小。
第二行包含一个正整数 $C~ (C\le 10^5)$,表示朋友们住的酒店个数。
接下来的 $C$ 行,每行两个正整数 $x,y ~(x\le N,y\le M)$ ,描述第 $i$ 个酒店的坐标。
紧跟着一行,包含一个正整数 $H~ (H\le 10^5)$ ,表示餐馆的个数。
接下来的 $H$ 行,每行两个正整数 $x,y$ ,以类似地格式给出餐馆的坐标。
注意有些餐馆和酒店的坐标可能相同。
输出格式:
第一行输出一个整数,表示距离的最大距离的最小可能值。
第二行输出一个整数,表示达到这个最优值的餐馆的编号。如果有多个餐馆均符合要求,输出任意一个均可。
我们只需要知道每个餐馆对应的最远酒店在哪里就好了
回忆小学数学,点到点集的最远距离怎么算的?
答案就是找点集的外接圆,然后枚举在外接圆上的点找最大的。
考虑曼哈顿距离的计算
那么这个点一定在Manhattan平面上所有人的“外接圆”上
这个Manhattan平面的外接圆长啥样呢,我搬了张图
下图是 Manhattan 平面上半径为 $1$ 的圆
考虑怎么求这个外接圆
观察公式 $|x_i-x_j|+|y_i-y_j|$ 可以发现,一共有 $4$ 种情况
这么看好像有点花,我们用 $a,b,c,d$ 来替代 $x_i,y_i,x_j,y_j$
而在枚举每个餐厅的时候,其实就相当于固定了 $c,d$ 。
于是我们只要统计每个人的 $a-b,-a-b,a+b,-a+b$ 各自的最大值,这样减掉后面的 $c,d$ 就是极大值了。
时间复杂度 $\mathcal{O}(4c+h)$
代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <cmath>
#include <iomanip>
#include <random>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N ((int)())
int n,m,c,h,p,s1,s2,s3,s4,res=INF;
void up(int &x,int y) {x < y ? x=y : 0;}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> n >> m >> c; s1=s2=s3=s4=-INF;
for(int i=1,x,y; i<=c; i++)
{
cin >> x >> y;
up(s1,x+y); up(s2,x-y); up(s3,-x+y); up(s4,-x-y);
}
cin >> h;
for(int i=1,x,y,t; i<=h; i++)
{
cin >> x >> y;
t=max({s1-(x+y), s2-(x-y), s3-(-x+y), s4-(-x-y)});
res > t ? res=t,p=i : 0;
}
cout << res << '\n' << p << '\n';
return 0;
}
参考文献: