bzoj3170[Tjoi 2013]松鼠聚会

有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

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 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define N 100007
 5 #define ll long long
 6 using namespace std;
 7 
 8 int n;
 9 double ans=1e20;
10 ll sx,sy,ax[N],bx[N],ay[N],by[N];
11 struct point
12 {
13     ll x,y;
14     int num;
15 }a[N];
16 
17 bool cmpx(point a,point b){return a.x<b.x;}
18 bool cmpy(point a,point b){return a.y<b.y;}
19 int main()
20 {
21     scanf("%d",&n);
22     for(int i=1;i<=n;i++)
23     {
24        ll x,y;
25        scanf("%lld%lld",&x,&y);
26        a[i].x=x+y;a[i].y=x-y;
27     }
28     sort(a+1,a+n+1,cmpy);
29     for(int i=1;i<=n;i++)
30     {
31         ay[i]=ay[i-1]+a[i].y;
32         by[n-i+1]=by[n-i+2]-a[n-i+1].y;
33         a[i].num=i;
34     }
35     sort(a+1,a+n+1,cmpx);
36     for(int i=1;i<=n;i++)
37     {
38         ax[i]=ax[i-1]+a[i].x;
39         bx[n-i+1]=bx[n-i+2]-a[n-i+1].x;
40     }
41     for(int i=1;i<=n;i++)
42     {
43         ll tmp=0;
44         tmp+=ax[n]-ax[i]-(n-i)*(ax[i]-ax[i-1]);
45         tmp+=bx[1]-bx[i]-(i-1)*(bx[i]-bx[i+1]);
46         int j=a[i].num;
47         tmp+=ay[n]-ay[j]-(n-j)*(ay[j]-ay[j-1]);
48         tmp+=by[1]-by[j]-(j-1)*(by[j]-by[j+1]);
49         if(tmp<ans)ans=tmp;
50     }
51     printf("%.0lf",ans/2);
52 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/7678286.html