3170: [Tjoi 2013]松鼠聚会
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1205 Solved: 600
[ Submit][ Status][ Discuss]
Description
有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。
Input
第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
下面N行,每行给出x,y表示其家的坐标。
-10^9<=x,y<=10^9
Output
表示为了聚会走的路程和最小为多少。
Sample Input
6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
Sample Output
20
做了奇怪的事情。。。
本来一个神奇的坐标转化就可以的,我用线段树强行维护了答案。
枚举每一个点为聚会的地方,周围就有八种情况(“米”字形地分开),每种情况中的点到聚会点的长度都是只用x或y,排好序丢到线段树里就可以了。
然后跑的常数是8,再加上线段树的常数,7s跑完,排行榜都不要我了。QAQ
#include <stdio.h>
#include <algorithm>
using namespace std;
//long long
const long long maxn = 140000;
const long long del = 110000;
struct node {
long long l , r , s , siz;
node *ll , *rr;
} pool[maxn*4] , *t;
struct dis {
long long x , i;
} d[maxn];
struct so {
long long x , y , b1 , b2 , i;
} s[maxn];
long long top;
long long n;
long long x[maxn] , y[maxn];
long long ans[maxn] , minn;
bool cmp ( dis x1 , dis x2 ) {
return x1.x < x2.x;
}
bool cmp1 ( so x1 , so x2 ) {
if ( x1.y == x2.y ) return x1.b1 < x2.b1;
return x1.y > x2.y;
}
bool cmp2 ( so x1 , so x2 ) {
if ( x1.x == x2.x ) return x1.b1 > x2.b1;
return x1.x > x2.x;
}
bool cmp3 ( so x1 , so x2 ) {
if ( x1.x == x2.x ) return x1.b2 < x2.b2;
return x1.x < x2.x;
}
bool cmp4 ( so x1 , so x2 ) {
if ( x1.y == x2.y ) return x1.b2 < x2.b2;
return x1.y > x2.y;
}
bool cmp5 ( so x1 , so x2 ) {
if ( x1.y == x2.y ) return x1.b1 < x2.b1;
return x1.y < x2.y;
}
bool cmp6 ( so x1 , so x2 ) {
if ( x1.x == x2.x ) return x1.b1 < x2.b1;
return x1.x < x2.x;
}
bool cmp7 ( so x1 , so x2 ) {
if ( x1.x == x2.x ) return x1.b2 > x2.b2;
return x1.x > x2.x;
}
bool cmp8 ( so x1 , so x2 ) {
if ( x1.y == x2.y ) return x1.b2 < x2.b2;
return x1.y < x2.y;
}
void buildtree ( node *id , long long l , long long r ) {
id -> l = l; id -> r = r;
if ( l == r ) return ;
long long mid = (l+r)/2;
id -> ll = &pool[++top]; id -> rr = &pool[++top];
buildtree ( id -> ll , l , mid ); buildtree ( id -> rr , mid + 1 , r );
}
void clear ( node *id ) {
id -> s = id -> siz = 0;
if ( id -> ll ) clear ( id -> ll );
if ( id -> rr ) clear ( id -> rr );
}
void change ( node *id , long long x , long long y ) {
//prlong longf ( "%lld %lld %lld %lld\n" , id -> l , id -> r , x , y );
id -> s += y; id -> siz++;
if ( id -> l == id -> r ) return ;
long long mid = (id->l+id->r)/2;
if ( x <= mid ) change ( id -> ll , x , y );
else change ( id -> rr , x , y );
}
long long querys ( node *id , long long l , long long r ) {
if ( l > r ) return 0;
if ( id -> l == l && id -> r == r ) return id -> s;
long long mid = (id->l+id->r)/2;
if ( r <= mid ) return querys ( id -> ll , l , r );
else {
if ( l > mid ) return querys ( id -> rr , l , r );
else return querys ( id -> ll , l , mid ) + querys ( id -> rr , mid + 1 , r );
}
}
long long querysiz ( node *id , long long l , long long r ) {
//prlong longf ( "%lld %lld %lld %lld\n" , id -> l , id -> r , l , r );
if ( l > r ) return 0;
if ( id -> l == l && id -> r == r ) return id -> siz;
long long mid = (id->l+id->r)/2;
if ( r <= mid ) return querysiz ( id -> ll , l , r );
else {
if ( l > mid ) return querysiz ( id -> rr , l , r );
else return querysiz ( id -> ll , l , mid ) + querysiz ( id -> rr , mid + 1 , r );
}
}
void work () {
long long i , k;
scanf ( "%lld" , &n );
for ( i = 1 ; i <= n ; i++ ) {
scanf ( "%lld%lld" , &s[i].x , &s[i].y );
s[i].i = i;
d[i].x = s[i].y - s[i].x; d[i].i = i;
}
sort ( d + 1 , d + 1 + n , cmp );
for ( i = 1 , k = 0 ; i <= n ; i++ ) {
if ( i == 1 || d[i].x != d[i-1].x ) k++;
s[d[i].i].b1 = k;
}
for ( i = 1 ; i <= n ; i++ ) d[i].x = s[i].x + s[i].y, d[i].i = i;
sort ( d + 1 , d + 1 + n , cmp );
for ( i = 1 , k = 0 ; i <= n ; i++ ) {
if ( i == 1 || d[i].x != d[i-1].x ) k++;
s[d[i].i].b2 = k;
}
//for ( i = 1 ; i <= n ; i++ ) printf ( "%lld %lld %lld %lld\n" , s[i].x , s[i].y , s[i].b1 , s[i].b2 );
t = &pool[++top];
buildtree ( t , 1 , n );
sort ( s + 1 , s + 1 + n , cmp1 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,1,s[i].b1) - querysiz(t,1,s[i].b1) * s[i].x);
change ( t , s[i].b1 , s[i].x );
//printf ( "###%lld %lld %lld\n" , i , s[i].b1 , s[i].b2 );
//printf ( "%lld %lld %lld %lld %lld\n" , querys(t,s[i].b2+1,n) , querysiz(t,s[i].b2+1,n) , s[i].i , s[i].b2 , abs(querys(t,s[i].b2+1,n) - querysiz(t,s[i].b2+1,n) * s[i].x) );
}
sort ( s + 1 , s + 1 + n , cmp2 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,s[i].b1+1,n) - querysiz(t,s[i].b1+1,n) * s[i].y);
//printf ( "%lld %lld %lld\n" , querys(t,1,s[i].b1) , querysiz(t,1,s[i].b1), s[i].i );
change ( t , s[i].b1 , s[i].y );
}
sort ( s + 1 , s + 1 + n , cmp3 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,s[i].b2,n) - querysiz(t,s[i].b2,n) * s[i].y);
change ( t , s[i].b2 , s[i].y );
}
sort ( s + 1 , s + 1 + n , cmp4 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,1,s[i].b2-1) - querysiz(t,1,s[i].b2-1) * s[i].x);
change ( t , s[i].b2 , s[i].x );
}
sort ( s + 1 , s + 1 + n , cmp5 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,s[i].b1,n) - querysiz(t,s[i].b1,n) * s[i].x);
change ( t , s[i].b1 , s[i].x );
}
sort ( s + 1 , s + 1 + n , cmp6 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,1,s[i].b1-1) - querysiz(t,1,s[i].b1-1) * s[i].y);
change ( t , s[i].b1 , s[i].y );
}
sort ( s + 1 , s + 1 + n , cmp7 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,1,s[i].b2) - querysiz(t,1,s[i].b2) * s[i].y);
change ( t , s[i].b2 , s[i].y );
}
//printf ( "%lld\n" , ans[5] );
sort ( s + 1 , s + 1 + n , cmp8 );
clear ( t );
for ( i = 1 ; i <= n ; i++ ) {
ans[s[i].i] += abs(querys(t,s[i].b2+1,n) - querysiz(t,s[i].b2+1,n) * s[i].x);
change ( t , s[i].b2 , s[i].x );
}
minn = ans[1];
for ( i = 2 ; i <= n ; i++ ) minn = min ( minn , ans[i] );
//for ( i = 1 ; i <= n ; i++ ) printf ( "%lld\n" , ans[i] );
printf ( "%lld\n" , minn );
}
int main () {
//FILE *fpr = freopen ( "bzoj3170.in" , "r" , stdin );
//FILE *fpw = freopen ( "bzoj3170.out" , "w" , stdout );
work ();
return 0;
}