「BZOJ3170」[TJOI2013] 松鼠聚会
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
题解
对于这题,我们可以得到d(i,j)=max(|xi-xj|,|yi-yj|),
设x’=(x+y)/2,y’=(x-y)/2
那么d(i,j)=|xi’-xj’|+|yi’-yj’|
x,y轴可以分开统计
先是统计x轴,将所有松鼠的x’排序
用前缀和和后缀和求出某个松鼠到其他松鼠的X轴距离
Xi*(i-1)-sum(1..i-1)+sum(i+1..n)-(n-i)*Xi
y轴同理
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 |
#include<iostream> #include<cstdio> #include<algorithm> #define N 100005 #define ll long long using namespace std; int n; struct point{ll x,y;int num;}a[N]; double ans=1e20; ll sx,sy,ax[N],bx[N],ay[N],by[N]; bool cmpx(point a,point b){return a.x<b.x;} bool cmpy(point a,point b){return a.y<b.y;} int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { ll x,y; scanf("%lld%lld",&x,&y); a[i].x=x+y;a[i].y=x-y; } sort(a+1,a+n+1,cmpy); for(int i=1;i<=n;i++) { ay[i]=ay[i-1]+a[i].y; by[n-i+1]=by[n-i+2]-a[n-i+1].y; a[i].num=i; } sort(a+1,a+n+1,cmpx); for(int i=1;i<=n;i++) { ax[i]=ax[i-1]+a[i].x; bx[n-i+1]=bx[n-i+2]-a[n-i+1].x; } for(int i=1;i<=n;i++) { ll tmp=0; tmp+=ax[n]-ax[i]-(n-i)*(ax[i]-ax[i-1]); tmp+=bx[1]-bx[i]-(i-1)*(bx[i]-bx[i+1]); int j=a[i].num; tmp+=ay[n]-ay[j]-(n-j)*(ay[j]-ay[j-1]); tmp+=by[1]-by[j]-(j-1)*(by[j]-by[j+1]); if(tmp<ans)ans=tmp; } printf("%.0lf",ans/2); return 0; } |
Subscribe