题目大意
给定一个二维平面和平面上的
n
个点。
求一个点,使得其他所有点到它的切比雪夫距离之和最小。
两点
Data Constraint
n≤100000
题解
如果是曼哈顿距离,那这题就很简单了,直接分类讨论一下,然后树状数组查询。
现在考虑如何将切比雪夫距离转化成曼哈顿距离。
切比雪夫距离转化曼哈顿距离
先将原平面旋转 45° ,那么点 (x,y) 就变成了 (x−y,x+y) ,然后在新的平面内求曼哈顿距离,可以发现,这恰好是原切比雪夫距离的两倍。
然后问题就顺利解决了。
时间复杂度: O(nlogn)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 100000 + 10
typedef long long ll ;
struct Note {
int v , h ;
} tpx[N] , tpy[N] ;
struct Point {
int x , y ;
Point ( int X = 0 , int Y = 0 ) { x = X , y = Y ; }
} P[N] ;
struct Tree {
ll sum ;
int tot ;
Tree ( ll S = 0 , int T = 0 ) { sum = S , tot = T ; }
} Tr[2][N] ;
Tree operator + ( Tree a , Tree b ) { return Tree( a.sum + b.sum , a.tot + b.tot ) ; }
int Orix[N] , Oriy[N] ;
int n , Cntx , Cnty ;
ll ans = 1e15 ;
bool cmp( Note a , Note b ) { return a.v < b.v ; }
void PreX() {
sort( tpx + 1 , tpx + n + 1 , cmp ) ;
tpx[0].v = 0x7FFFFFFF ;
for (int i = 1 ; i <= n ; i ++ ) {
if ( tpx[i].v != tpx[i-1].v ) ++ Cntx ;
Orix[Cntx] = P[tpx[i].h].x ;
P[tpx[i].h].x = Cntx ;
}
}
void PreY() {
sort( tpy + 1 , tpy + n + 1 , cmp ) ;
tpy[0].v = 0x7FFFFFFF ;
for (int i = 1 ; i <= n ; i ++ ) {
if ( tpy[i].v != tpy[i-1].v ) ++ Cnty ;
Oriy[Cnty] = P[tpy[i].h].y ;
P[tpy[i].h].y = Cnty ;
}
}
int lowbit( int x ) { return x & (-x) ; } ;
void Insert( int k , int x , Tree del ) {
while ( x <= n ) {
Tr[k][x] = Tr[k][x] + del ;
x += lowbit(x) ;
}
}
Tree Find( int k , int x ) {
Tree ret = Tree(0,0) ;
while ( x >= 1 ) {
ret = ret + Tr[k][x] ;
x -= lowbit(x) ;
}
return ret ;
}
int main() {
scanf( "%d" , &n ) ;
for (int i = 1 ; i <= n ; i ++ ) {
scanf( "%d%d" , &P[i].x , &P[i].y ) ;
P[i] = Point( P[i].x - P[i].y , P[i].x + P[i].y ) ;
tpx[i].v = P[i].x ;
tpy[i].v = P[i].y ;
tpx[i].h = tpy[i].h = i ;
}
PreX() ;
PreY() ;
for (int i = 1 ; i <= n ; i ++ ) {
Insert( 0 , P[i].x , Tree( Orix[P[i].x] , 1 ) ) ;
Insert( 1 , P[i].y , Tree( Oriy[P[i].y] , 1 ) ) ;
}
for (int i = 1 ; i <= n ; i ++ ) {
ll now = 0 ;
Tree All = Find( 0 , Cntx ) ;
Tree Lef = Find( 0 , P[i].x - 1 ) ;
Tree Rig = Tree( All.sum - Lef.sum , All.tot - Lef.tot ) ;
now = (ll)Lef.tot * Orix[P[i].x] - Lef.sum ;
now += Rig.sum - (ll)Rig.tot * Orix[P[i].x] ;
All = Find( 1 , Cnty ) ;
Lef = Find( 1 , P[i].y - 1 ) ;
Rig = Tree( All.sum - Lef.sum , All.tot - Lef.tot ) ;
now += (ll)Lef.tot * Oriy[P[i].y] - Lef.sum ;
now += (ll)Rig.sum - (ll)Rig.tot * Oriy[P[i].y] ;
ans = min( ans , now ) ;
}
printf( "%lld\n" , ans / 2 ) ;
return 0 ;
}
以上.