嘘~ 正在从服务器偷取页面 . . .

CF491B New York Hotel 题解


CF491B New York Hotel 题解

题目链接: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\) ,以类似地格式给出餐馆的坐标。

注意有些餐馆和酒店的坐标可能相同。

输出格式

第一行输出一个整数,表示距离的最大距离的最小可能值。

第二行输出一个整数,表示达到这个最优值的餐馆的编号。如果有多个餐馆均符合要求,输出任意一个均可。

我们只需要知道每个餐馆对应的最远酒店在哪里就好了

回忆小学数学,点到点集的最远距离怎么算的?

答案就是找点集的外接圆,然后枚举在外接圆上的点找最大的。

考虑曼哈顿距离的计算 \[ d(i,j)=|x_i-x_j|+|y_i-y_j| \] 那么这个点一定在Manhattan平面上所有人的“外接圆”上

这个Manhattan平面的外接圆长啥样呢,我搬了张图

下图是 Manhattan 平面上半径为 \(1\) 的圆


考虑怎么求这个外接圆

观察公式 \(|x_i-x_j|+|y_i-y_j|\) 可以发现,一共有 \(4\) 种情况 \[ (x_i-x_j)-(y_i-y_j)\\ (x_j-x_i)-(y_i-y_j)\\ (x_i-x_j)-(y_j-y_i)\\ (x_j-x_i)-(y_j-y_i) \] 这么看好像有点花,我们用 \(a,b,c,d\) 来替代 \(x_i,y_i,x_j,y_j\) \[ \begin{aligned} (a-c)-(b-d) &\Rightarrow (a-b)-(c-d)\\ (c-a)-(b-d) &\Rightarrow (-a-b)-(-c-d)\\ (a-c)-(d-b) &\Rightarrow (a+b)-(c+d)\\ (c-a)-(d-b) &\Rightarrow (-a+b)-(-c+d) \end{aligned} \] 而在枚举每个餐厅的时候,其实就相当于固定了 \(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;
}

参考文献

[1] https://yhx-12243.github.io/OI-transit/?redirect=227

[2] https://oi-wiki.org/geometry/distance/


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录