You and your friends live in n n n houses. Each house is located on a 2D plane, in a point with integer coordinates. There might be different houses located in the same point. The mayor of the city is asking you for places for the building of the Eastern exhibition. You have to find the number of places (points with integer coordinates), so that the summary distance from all the houses to the exhibition is minimal. The exhibition can be built in the same point as some house. The distance between two points ( x 1 , y 1 ) (x_1,y_1) ( x 1 , y 1 ) and ( x 2 , y 2 ) (x_2,y_2) ( x 2 , y 2 ) is ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ |x_1−x_2|+|y_1−y_2| ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ , where ∣ x ∣ |x| ∣ x ∣ is the absolute value of x x x .
First line contains a single integer t t t (1 ≤ t ≤ 1000 1≤t≤1000 1 ≤ t ≤ 1000 ) — the number of test cases.
The first line of each test case contains a single integer n n n ( 1 ≤ n ≤ 1000 ) (1≤n≤1000) ( 1 ≤ n ≤ 1000 ) . Next n n n lines describe the positions of the houses ( x i , y i ) (x_i,y_i) ( x i , y i ) (0 ≤ x i , y i ≤ 1 0 9 ) 0≤x_i,y_i≤10^9) 0 ≤ x i , y i ≤ 1 0 9 ) .
It’s guaranteed that the sum of all n n n does not exceed 1000 1000 1000 .
Output
For each test case output a single integer - the number of different positions for the exhibition. The exhibition can be built in the same point as some house.
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 6 3 0 0 2 0 1 2 4 1 0 0 2 2 3 3 1 4 0 0 0 1 1 0 1 1 2 0 0 1 1 2 0 0 2 0 2 0 0 0 0
output
Note
Here are the images for the example test cases. Blue dots stand for the houses, green — possible positions for the exhibition.
First test case.
Second test case.
Third test case.
Fourth test case.
Fifth test case.
Sixth test case. Here both houses are located at ( 0 , 0 ) (0,0) ( 0 , 0 ) .
Idea
假设最后选定的坐标为 ( X , Y ) (X,Y) ( X , Y ) 。设坐标 x i ≤ X x_i\le X x i ≤ X 的个数有 u u u ,而 x i > X x_i>X x i > X 的坐标有 v v v ,则 X X X 产生的路程贡献为 ( u X − ∑ x i ≤ X x i ) + ( ∑ x i > X x i − v X ) (uX-\sum\limits_{x_i\le X}x_i)+(\sum\limits_{x_i>X}x_i-vX) ( u X − x i ≤ X ∑ x i ) + ( x i > X ∑ x i − v X ) ;对于 Y Y Y 的路程贡献,同理。从式中可以看出,X X X 和 Y Y Y 相互独立,互不产生影响。接下来只讨论 X X X 的取值。
考虑枚举 u u u ,我们先将 x x x 序列升序排列;枚举到 x i x_i x i 时,对于 x i ∼ x i + 1 x_i\sim x_{i+1} x i ∼ x i + 1 种的任何 X X X 值,都有 u = i u=i u = i 且 v = n − i v=n-i v = n − i ;令 s u m i = ∑ j = 1 i x j sum_i=\sum\limits_{j=1}^i x_j s u m i = j = 1 ∑ i x j ,则 X X X 产生的贡献为 ( 2 i − n ) X + s u m n − 2 s u m i (2i-n)X+sum_n-2sum_i ( 2 i − n ) X + s u m n − 2 s u m i ,其中 x i ≤ X < x i + 1 x_i\le X<x_{i+1} x i ≤ X < x i + 1 。显然,对于 2 i − n < 0 2i-n<0 2 i − n < 0 ,X = x i X=x_i X = x i 为最优;对于 2 i − n > 0 2i-n>0 2 i − n > 0 ,X = x i + 1 − 1 X=x_{i+1}-1 X = x i + 1 − 1 为最优;对于 2 n − i = 0 2n-i=0 2 n − i = 0 ,X X X 可取 [ x i , x i + 1 − 1 ] [x_i,x_{i+1}-1] [ x i , x i + 1 − 1 ] 中的任意正整数。
用unordered_map<long long,long long>
记录贡献为 C C C 的 X X X 的个数。
值得注意一些细节:若某一 X X X 值已经被取过,不可重复计数,需要用unordered_set
记录;考虑 X = x n X=x_n X = x n 和 X = x 1 X=x_1 X = x 1 的边界情况;一定要注意枚举到 x i x_i x i 时 X X X 的取值范围。
Y Y Y 的计算与之同理。
假设 X X X 产生的最小的路程贡献为 C X m i n C_{Xmin} C X min ,同理可定义 C Y m i n C_{Ymin} C Ymin ;取到 C X m i n C_{Xmin} C X min 的 X X X 个数为 c x c_x c x ,同理有 c y c_y c y ;答案为 c x × c y c_x\times c_y c x × c y 。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 #include <unordered_map> #include <iostream> #include <algorithm> #include <unordered_set> using namespace std;typedef long long ll;const int N=1003 ;int _;int n;ll x[N],y[N]; unordered_map<ll,ll>costNumX,costNumY; ll sumX[N],sumY[N]; unordered_set<int >visX,visY; ll leastCostX,leastCostY; int nx,ny;int main () { for (cin>>_;_;_--){ cin>>n; for (int i=1 ;i<=n;i++){ cin>>x[i]>>y[i]; } sort (x+1 ,x+1 +n); sort (y+1 ,y+1 +n); for (int i=1 ;i<=n;i++){ sumX[i]=sumX[i-1 ]+x[i]; sumY[i]=sumY[i-1 ]+y[i]; } costNumX.clear (); visX.clear (); costNumY.clear (); visY.clear (); for (int i=1 ;i<=n;i++){ if (i>n-i){ const ll X=x[i]; const ll Y=y[i]; const ll costX=(2 *i-n)*X-2 *sumX[i]+sumX[n]; const ll costY=(2 *i-n)*Y-2 *sumY[i]+sumY[n]; if (visX.find (X)==visX.end ()){ costNumX[costX]++; visX.insert (X); } if (visY.find (Y)==visY.end ()){ visY.insert (Y); costNumY[costY]++; } }else if (i<n-i){ if (i<n){ const ll X=max (x[i+1 ]-1 ,x[i]); const ll Y=max (y[i+1 ]-1 ,y[i]); const ll costX=(2 *i-n)*X-2 *sumX[i]+sumX[n]; const ll costY=(2 *i-n)*Y-2 *sumY[i]+sumY[n]; if (visX.find (X)==visX.end ()){ costNumX[costX]++; visX.insert (X); } if (visY.find (Y)==visY.end ()){ visY.insert (Y); costNumY[costY]++; } }else { const ll X=x[n]; const ll Y=y[n]; const ll costX=n*X-sumX[n]; const ll costY=n*Y-sumY[n]; if (visX.find (X)==visX.end ()){ costNumX[costX]++; visX.insert (X); } if (visY.find (Y)==visY.end ()){ visY.insert (Y); costNumY[costY]++; } } }else { const ll X=x[i]; const ll Y=y[i]; const ll costX=(2 *i-n)*X-2 *sumX[i]+sumX[n]; const ll costY=(2 *i-n)*Y-2 *sumY[i]+sumY[n]; if (i<n){ if (visX.find (X)==visX.end ()){ costNumX[costX]+=max (x[i+1 ]-x[i],1ll ); visX.insert (X); }else { costNumX[costX]+=max (x[i+1 ]-x[i]-1 ,0ll ); } if (visY.find (Y)==visY.end ()){ visY.insert (Y); costNumY[costY]+=max (y[i+1 ]-y[i],1ll ); }else { costNumY[costY]+=max (y[i+1 ]-y[i]-1 ,0ll ); } } } } leastCostX=leastCostY=0x7f7f7f7f7f7f7f7f ; for (auto & cX:costNumX){ leastCostX=min (leastCostX,cX.first); } for (auto & cY:costNumY){ leastCostY=min (leastCostY,cY.first); } cout<<costNumX[leastCostX]*costNumY[leastCostY]<<endl; } return 0 ; }