4 6 -4 -1 -1 -2 2 -4 0 2 0 3 5 -2 6 0 0 2 0 -5 -2 2 -2 -1 2 4 0 5 -5 1 -1 3 3 1 3 -1 1 -1 10 -1 -1 -3 2 -4 4 5 2 5 -4 3 -1 4 3 -1 -2 3 4 -2 2
26 20 20 56Hint
平面上两点间的 Manhattan 距离为 |x1-x2| + |y1-y2|
X 方向的距离与 Y 方向上的距离可以分开来处理。假设我们以 (xi,yi) 作为开会的地点,那么其余的点到该开会地点所需的时间为 X 方向上到 xi 所需要的时间加上 Y 方向上到 yi 所需要的时间。
对数据预处理后可以快速地求出x坐标小于xi的点的个数rankx, 并且这些 x 坐标值之和 sumx,那么这些点 X 方向上对结果的贡献为 rankx * xi - sumx;同理可以处理出 x 坐标大于 xi 的点在 X 方向上对结果的贡献值。同理可求得其余点在 Y 方向上到达 yi 所需要的总时间。
注意INF的值要取足够大,不然不停地wa,最后发现取1LL<<63-1就行了
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> using namespace std; const long long INF = 1LL<<63-1; struct acmers{ long long x; long long y; long long sum; }a[100010]; bool cmp1(acmers a, acmers b){ return a.x < b.x; } bool cmp2(acmers a, acmers b){ return a.y < b.y; } int main(){ long long t; long long i; long long n; long long rankx, ranky, rankxr, rankyd; long long sumxl, sumxr; long long sumyu, sumyd; scanf("%I64d", &t); while(t --){ scanf("%I64d", &n); sumxr = 0; sumyd = 0; for(i = 0; i < n; i ++){ scanf("%I64d %I64d", &a[i].x, &a[i].y); a[i].sum = 0; sumxr += a[i].x; sumyd += a[i].y; } //cout << "sumxr" << sumxr << endl; //cout << "sumyd" << sumyd << endl; sort(a, a+n, cmp1); sumxl = 0; rankx = 0; rankxr = n; for(rankx = 0; rankx < n; rankx ++){ sumxr -= a[rankx].x; rankxr--; a[rankx].sum += rankx * a[rankx].x - sumxl + sumxr - rankxr * a[rankx].x; sumxl += a[rankx].x; } sort(a, a + n, cmp2); sumyu = 0; ranky = 0; rankyd = n; for(ranky = 0; ranky < n; ranky ++){ sumyd -= a[ranky].y; rankyd--; a[ranky].sum += ranky * a[ranky].y - sumyu + sumyd - rankyd * a[ranky].y; sumyu += a[ranky].y; } long long mm = INF; for(i = 0; i < n; i ++){ if (a[i].sum < mm) mm = a[i].sum; } cout << mm << endl; } return 0; }