给在给你二维平面上的 n 个点 (xi,yi) ,现在规定从一个格点走到八相邻的格点的费用是1。现在要求你选出其中一个给定的点,要求其余所有点到这个点的花费和最小。
n≤105
xi,yi≤109
首先先分析一下怎样能更简便的算费用,不难发现,由于每走一步可以是横坐标距离减1或纵坐标距离减1,或两个同时减1。那么从一个点走到另一个点的代价显然是 max(|x1−x2|,|y1−y2|) 。这个距离的定义有一种更好听的名字——切比雪夫距离。
但是由于同时存在绝对值和取 max ,很难处理,但是众所周知,假如是求曼哈顿距离,只需把横坐标和纵坐标分开讨论,然后对每个排一下序,分别求大于某个值和小于某个值的贡献就行了。
所以我们考虑转成曼哈顿距离来解决此题。
考虑转化一下求切比雪夫距离的公式:
设 x3=x1+y1,y3=x1−y1,x4=x2+y2,y4=x2−y2 。把 x3,y3,x4,y4 重新代入到切比雪夫距离式子中表示 x1,y2 ,我们就可以发现它的形式就变成了:
//YxuanwKeith
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 5;
const int Inf = 1e9 + 7;
struct Node {
int x, y;
Node(int a, int b) {x = a, y = b;}
Node() {}
};
Node P[MAXN];
int n, Ox[MAXN], Oy[MAXN], Belx[MAXN], Bely[MAXN];
LL Sufx[MAXN], Sufy[MAXN], Prex[MAXN], Prey[MAXN];
bool CmpX(int A, int B) {
return P[A].x < P[B].x;
}
bool CmpY(int A, int B) {
return P[A].y < P[B].y;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++) {
int x, y;
scanf("%d%d", &x, &y);
P[i] = Node(x + y, x - y);
}
for (int i = 1; i <= n; i ++) Ox[i] = Oy[i] = i;
sort(Ox + 1, Ox + 1 + n, CmpX);
sort(Oy + 1, Oy + 1 + n, CmpY);
for (int i = 1; i <= n; i ++) Belx[Ox[i]] = i;
for (int i = 1; i <= n; i ++) Bely[Oy[i]] = i;
for (int i = 1; i <= n; i ++) Prex[i] = Prex[i - 1] + P[Ox[i]].x;
for (int i = 1; i <= n; i ++) Prey[i] = Prey[i - 1] + P[Oy[i]].y;
for (int i = n; i; i --) Sufx[i] = Sufx[i + 1] + P[Ox[i]].x;
for (int i = n; i; i --) Sufy[i] = Sufy[i + 1] + P[Oy[i]].y;
LL Ans = 1ll << 62;
for (int i = 1; i <= n; i ++) {
int Sx = Belx[i];
LL Sumx = 1ll * Sx * P[i].x - Prex[Sx] + Sufx[Sx + 1] - 1ll * (n - Sx) * P[i].x;
int Sy = Bely[i];
LL Sumy = 1ll * Sy * P[i].y - Prey[Sy] + Sufy[Sy + 1] - 1ll * (n - Sy) * P[i].y;
if (Sumx + Sumy < Ans) Ans = Sumx + Sumy;
}
printf("%lld\n", Ans / 2);
}