洛谷P3964

代码:
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
int main() {
int n;
cin >> n;
vector<LL> u(n), v(n);
for (int i = 0; i < n; i++) {
LL x, y;
cin >> x >> y;
u[i] = x + y;
v[i] = x - y;
}
// 处理u数组:排序并计算前缀和
vector<LL> sorted_u = u;
sort(sorted_u.begin(), sorted_u.end());
vector<LL> prefix_u(n + 1, 0);
for (int i = 0; i < n; i++) {
prefix_u[i + 1] = prefix_u[i] + sorted_u[i];
}
// 处理v数组:排序并计算前缀和
vector<LL> sorted_v = v;
sort(sorted_v.begin(), sorted_v.end());
vector<LL> prefix_v(n + 1, 0);
for (int i = 0; i < n; i++) {
prefix_v[i + 1] = prefix_v[i] + sorted_v[i];
}
LL min_total = 1e18;
// 遍历每个点,计算其对应的sum_u + sum_v
for (int i = 0; i < n; i++) {
LL ui = u[i];
// 计算sum(|u_j - ui|)
int k = lower_bound(sorted_u.begin(), sorted_u.end(), ui) - sorted_u.begin();
LL sum_u = ui * k - prefix_u[k] + (prefix_u[n] - prefix_u[k]) - ui * (n - k);
LL vi = v[i];
// 计算sum(|v_j - vi|)
int m = lower_bound(sorted_v.begin(), sorted_v.end(), vi) - sorted_v.begin();
LL sum_v = vi * m - prefix_v[m] + (prefix_v[n] - prefix_v[m]) - vi * (n - m);
LL total = sum_u + sum_v;
if (total < min_total) {
min_total = total;
}
}
cout << min_total / 2 << endl;
return 0;
}
由题意八个格子都可以走那么就是切比雪夫距离切比雪夫坐标。我们要求距离和,转化成曼哈顿距离比较好求。

从图片可以知道,代码将切比雪夫距离转化成曼哈顿距离,只是除2操作在最后进行。
然后因为曼哈顿距离的特性,x坐标和y坐标可以分开计算,然后因为是排序后的坐标又因为下面:

所以可以通过前缀和快速求的。