题意
从 $n$ 个点中选择一点,使得其他点到其的切比雪夫距离最小($0 < n leq 1e5$).
分析
定理:$(x_1, y_1)$ 与 $(x_2, y_2)$ 的曼哈顿距离等于 $(x_1-y_1, x_1+y_1)$ 与 $(x_2-y_2, x_2+y_2)$ 的切比雪夫距离。
转换成曼哈顿距离中的坐标,求曼哈顿距离。
由于这个点必须是 $n$ 个点中的一点,所以 $x,y$ 还有限制关系(不然直接排序取中点就完事了)。
我们对分别对 $x,y$ 排序并求出前缀和,
然后枚举这 $n$ 个点,对于每个点,可以 $O(log n)$ 得到 $x$ 方向和 $y$ 方向的绝对值之和,两者相加即是答案。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll INF = (1LL) << 60; const int maxn = 1e5 + 10; int n, x[maxn], y[maxn], sx[maxn], sy[maxn];; ll sum_x[maxn], sum_y[maxn]; struct Node{ int x, y, id; }p[maxn]; int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 1;i <= n;i++) { int a, b; scanf("%d%d", &a, &b); x[i] = sx[i] = a+b; y[i] = sy[i] = b-a;; //为了保证为整数,扩大了两倍 } sort(sx+1, sx+n+1); sort(sy+1, sy+n+1); for(int i = 1;i <= n;i++) { sum_x[i] = sum_x[i-1] + sx[i]; sum_y[i] = sum_y[i-1] + sy[i]; } ll ans = INF; for(int i = 1;i <= n;i++) //枚举每个点 { ll px = lower_bound(sx+1, sx+n+1, x[i]) - sx; //如果之前记录下来,就可以O(1) ll py = lower_bound(sy+1, sy+n+1, y[i]) - sy; ll tmp = px*x[i] - sum_x[px] + sum_x[n] - sum_x[px] - (n-px)*x[i]; //相乘爆int tmp += py*y[i] - sum_y[py] + sum_y[n] - sum_y[py] - (n-py)*y[i]; if(tmp < ans) ans = tmp; } printf("%lld ", ans/2); } }