松鼠聚会
题目描述
草原上住着一群小松鼠,每个小松鼠都有一个家。时间长了,大家觉得应该聚一聚。但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理。
每个小松鼠的家可以用一个点x,y表示,两个点的距离定义为点(x,y)和它周围的8个点(x-1,y)(x+1,y),(x,y-1),(x,y+1).(x-1,y+1),(x-1,y-1),(x+1,y+1),(x+1,y-1)距离为1。
输入输出格式
输入格式:
第一行是一个整数N,表示有多少只松鼠。接下来N行,第i行是两个整数x和y,表示松鼠i的家的坐标
输出格式:
一个整数,表示松鼠为了聚会走的路程和最小是多少。
输入输出样例
说明
样例解释
在第一个样例中,松鼠在第二只松鼠家(-1,-2)聚会;在第二个样例中,松鼠在第一只松鼠家(0.0)聚会。
数据范围
30%的数据,0 ≤ N ≤ 1000
100%的数据,0 ≤ N ≤ 100000; −10^9 ≤ x, y ≤ 10^9
分析:
这道奇妙的题让蒟蒻认识了切比雪夫距离这个奇妙的东西,关于切比雪夫距离可以参照julao的博客。
关于这道题,我们把切比雪夫距离转换成曼哈顿距离,然后用前缀和+二分答案优化一下就可以了。
Code:
//It is made by HolseLee on 6th Nov 2018 //Luogu.org P3964 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+7; int n,x[N],y[N],px[N],py[N]; ll sumx[N],sumy[N],ans; inline int read() { char ch=getchar(); int x=0; bool flag=false; while( ch<'0' || ch>'9' ) { if( ch=='-' ) flag=true; ch=getchar(); } while( ch>='0' && ch<='9' ) { x=x*10+ch-'0'; ch=getchar(); } return flag ? -x : x; } void getsum() { for(int i=1; i<=n; ++i) sumx[i]=sumx[i-1]+x[i]; for(int i=1; i<=n; ++i) sumy[i]=sumy[i-1]+y[i]; } inline ll binary_x(int u) { ll l=1, r=n, mid,ret=n; while( l<=r ) { mid=(l+r)>>1; if( x[mid]<=px[u] ) ret=mid, l=mid+1; else r=mid-1; } return ret; } inline ll binary_y(int u) { ll l=1, r=n, mid,ret=n; while( l<=r ) { mid=(l+r)>>1; if( y[mid]<=py[u] ) ret=mid, l=mid+1; else r=mid-1; } return ret; } inline ll getans(int u) { ll xpos=binary_x(u); ll ansx=xpos*px[u]-sumx[xpos]+sumx[n]-sumx[xpos]-(n-xpos)*px[u]; ll ypos=binary_y(u); ll ansy=ypos*py[u]-sumy[ypos]+sumy[n]-sumy[ypos]-(n-ypos)*py[u]; return ansx+ansy; } int main() { n=read(); int a,b; for(int i=1; i<=n; ++i) { a=read(), b=read(); x[i]=px[i]=a+b; y[i]=py[i]=a-b; } sort(x+1,x+n+1); sort(y+1,y+n+1); getsum(); ans=1e18; for(int i=1; i<=n; ++i) { ll now=getans(i); ans=min(now,ans); } printf("%lld ",ans>>1ll); return 0; }