1. 程式人生 > >P3964 [TJOI2013]松鼠聚會

P3964 [TJOI2013]松鼠聚會

read min tro 處理 lld tmp reg ret ()

題目描述

草原上住著一群小松鼠,每個小松鼠都有一個家。時間長了,大家覺得應該聚一聚。但是草原非常大,松鼠們都很頭疼應該在誰家聚會才最合理。

每個小松鼠的家可以用一個點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:
6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
輸出樣例#1:
20
輸入樣例#2:
6
0 0
2 0
-5 -2
2 -2
-1 2
4 0
輸出樣例#2:
15

說明

樣例解釋

在第一個樣例中,松鼠在第二只松鼠家(-1,-2)聚會;在第二個樣例中,松鼠在第一只松鼠家(0.0)聚會。

數據範圍

30%的數據,0 ≤ N ≤ 1000

100%的數據,0 ≤ N ≤ 100000; −10^9 ≤ x, y ≤ 10^9

做法

本題兩點間的距離是max(|x1-x2|,|y1-y2|),曾經在黃學長的博客裏看到過一個轉化

求這個距離可以把點的坐標都轉化成 (x+y)/2,(x-y)/2 然後的曼哈頓距離就是這個了

這個好像叫 切比雪夫距離

之後我們預處理前綴和,枚舉源點就可以了。

記得都開longlong 我WA的很悲慘

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int read(){
    int x=0,t=1;char c=getchar();
    while(c<0||c>9){if(c==-)t=-1;c=getchar();}
    while(c>=
0&&c<=9){x=x*10+c-0;c=getchar();} return x*t; } struct Node{ long long X,Y; }a[MAXN]; int N,x[MAXN],y[MAXN],pos; long long ans=1ll<<62,s1[MAXN],s2[MAXN]; int main() { N=read(); for(int i=1;i<=N;i++){ int p=read(),q=read(); x[i]=a[i].X=p+q; y[i]=a[i].Y=p-q; } sort(x+1,x+N+1); sort(y+1,y+N+1); for(int i=1;i<=N;i++) s1[i]=s1[i-1]+x[i], s2[i]=s2[i-1]+y[i]; for(int i=1;i<=N;i++){ long long tmp=0; pos=lower_bound(x+1,x+N+1,a[i].X)-x; tmp+=s1[N]-s1[pos]-a[i].X*(N-pos)+a[i].X*pos-s1[pos]; pos=lower_bound(y+1,y+N+1,a[i].Y)-y; tmp+=s2[N]-s2[pos]-a[i].Y*(N-pos)+a[i].Y*pos-s2[pos]; ans=min(ans,tmp); } printf("%lld\n",ans/2); return 0; }

P3964 [TJOI2013]松鼠聚會