传送门:点击打开链接
题意:一个二维网状格点,先给一个n,然后有n个坐标,表示最开始n个人的坐标,然后给一个m,然后有m个坐标,现在要从m个坐标中选出一个坐标,使得这个坐标到n个坐标的最大距离最小输出最大距离最小是多少,以及最后选出的是m个点中的哪一个, n,m<=1e5,坐标有x和y,均<=1e9
思路:这题还真一下子转不过弯来了- -
首先,很明显答案应该是min{|N[i].x-M[j].x|+|N[i].y-M[j].y|},1<=i<=n,1<=j<=m
问题是,我们如何能快速求出,对于点(M[j].x,M[j].y),距离它最远的距离是多少
其实我们能够发现,|N[i].x-M[j].x|+|N[i].y-M[j].y|有4种去绝对值的方式。
然后我们能发现,加了绝对值是4种去绝对值方式中最大的。
所以我们直接维护4种取了绝对值的最大值,然后对于某次查询,直接取最大的不就行了- -
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int>PII; const int MX = 1e5 + 5; const int mod = 1e9 + 7; const LL INF = 0x3f3f3f3f3f3f3f3f; int main() { //FIN; while(~scanf("%*d%*d")) { int n, m; scanf("%d", &n); LL Max[4], x, y; memset(Max, -INF, sizeof(Max)); for(int i = 1; i <= n; i++) { scanf("%I64d%I64d", &x, &y); Max[0] = max(Max[0], x + y); Max[1] = max(Max[1], x - y); Max[2] = max(Max[2], -x + y); Max[3] = max(Max[3], -x - y); } scanf("%d", &m); LL ans = INF; int id = 0; for(int i = 1; i <= m; i++) { scanf("%I64d%I64d", &x, &y); LL t = -INF; t = max(t, Max[0] - x - y); t = max(t, Max[1] - x + y); t = max(t, Max[2] + x - y); t = max(t, Max[3] + x + y); if(t < ans) ans = t, id = i; } printf("%I64d\n%d\n", ans, id); } return 0; }