枚举每个点是必须的,问题就在于如何快速求出曼哈顿距离之和。可以将x坐标和y坐标分别排序,枚举到点(xx,yy)的时候在排好序的x和y数组中二分找到其位置,然后之前的数字都小于,之后的数字都大于,就可以去掉绝对值了。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 typedef long long ll; 8 const ll INF = 9999999999999999; 9 const int N = 100000; 10 int x[N]; 11 int y[N]; 12 ll sumx[N]; 13 ll sumy[N]; 14 ll ans; 15 16 struct Point 17 { 18 int x, y; 19 } point[N]; 20 21 int main () 22 { 23 int t; 24 scanf("%d", &t); 25 while ( t-- ) 26 { 27 int n; 28 scanf("%d", &n); 29 for ( int i = 0; i < n; i++ ) 30 { 31 scanf("%d", x + i); 32 scanf("%d", y + i); 33 point[i].x = x[i]; 34 point[i].y = y[i]; 35 } 36 sort( x, x + n ); 37 sort( y, y + n ); 38 sumx[0] = x[0]; 39 sumy[0] = y[0]; 40 for ( int i = 1; i < n; i++ ) 41 { 42 sumx[i] = sumx[i - 1] + x[i]; 43 sumy[i] = sumy[i - 1] + y[i]; 44 } 45 ans = INF; 46 for ( int i = 0; i < n; i++ ) 47 { 48 int xx = point[i].x; 49 int yy = point[i].y; 50 int posx = upper_bound( x, x + n, xx ) - x; 51 int posy = upper_bound( y, y + n, yy ) - y; 52 ll tmpx = ( ll ) posx * xx - sumx[posx - 1] + sumx[n - 1] 53 - sumx[posx - 1] - ( ll ) ( n - posx ) * xx; 54 ll tmpy = ( ll ) posy * yy - sumy[posy - 1] + sumy[n - 1] 55 - sumy[posy - 1] - ( ll ) ( n - posy ) * yy; 56 if ( tmpx + tmpy < ans ) 57 { 58 ans = tmpx + tmpy; 59 } 60 } 61 printf("%I64d\n", ans); 62 } 63 return 0; 64 }