【BZOJ】【3170】【TJOI2103】松鼠聚会
切比雪夫距离+曼哈顿距离
题解:http://www.cnblogs.com/zyfzyf/p/4105456.html
其实应该先做这题再做【BZOJ】【3210】花神的浇花集会的吧……
我们发现dist(i,j)是 i 和 j 的切比雪夫距离,那么同样的,我们可以将它们转成曼哈顿来做。(x[i]=x+y; y[i]=x-y;)
然后就是求n个点到某一个点的曼哈顿距离和的最小值了。
由于是曼哈顿距离,所以x和y是无关的,我们可以分开计算!
对x排序,我们可以发现,所有点到x[1]的距离就是$\sum_{i=2}^n (x[i]-x[1])=\sum_{i=2}^n x[i] - x[1]*(n-1)$
我们发现求和的哪一项$\sum_{i=2}^n x[i]$其实就是后缀和。
同理,到x[2]的也是跟前缀和&后缀和有关,那么就可以O(n)来扫一遍来做了……
y方向同理……也是正着扫一遍,倒着扫一遍。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 3170 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:424 ms 7 Memory:2840 kb 8 ****************************************************************/ 9 10 //BZOJ 3170 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=1e5+10; 29 /*******************template********************/ 30 31 int n; 32 struct node{ 33 int x,y; LL z; 34 }a[N]; 35 inline bool cmp1(node a,node b){return a.x<b.x;} 36 inline bool cmp2(node a,node b){return a.y<b.y;} 37 int main(){ 38 #ifndef ONLINE_JUDGE 39 freopen("3170.in","r",stdin); 40 freopen("3170.out","w",stdout); 41 #endif 42 n=getint(); 43 F(i,1,n){ 44 int x=getint(),y=getint(); 45 a[i].x=x+y; a[i].y=x-y; 46 } 47 sort(a+1,a+n+1,cmp1); 48 LL sum=0; 49 F(i,1,n){ 50 a[i].z+=(LL)a[i].x*(i-1)-sum; 51 sum+=a[i].x; 52 } 53 sum=0; 54 D(i,n,1){ 55 a[i].z+=sum-(LL)a[i].x*(n-i); 56 sum+=a[i].x; 57 } 58 sort(a+1,a+n+1,cmp2); 59 sum=0; 60 F(i,1,n){ 61 a[i].z+=(LL)a[i].y*(i-1)-sum; 62 sum+=a[i].y; 63 } 64 sum=0; 65 D(i,n,1){ 66 a[i].z+=sum-(LL)a[i].y*(n-i); 67 sum+=a[i].y; 68 } 69 LL ans=1e18; 70 F(i,1,n) ans=min(ans,a[i].z); 71 printf("%lld\n",ans>>1); 72 return 0; 73 }
3170: [Tjoi 2013]松鼠聚会
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 720 Solved: 326
[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