松鼠的聚會
description
有若干只松鼠住在可視為笛卡爾座標系的草原上,它們想選定其中一隻的家作為目的地去參加聚會,並且不希望走太長距離,請你求出最小距離.值得注意的是,一個點到其周圍八個點距離均為$ 1 $.
solution
此題我們不難發現,任意兩點間的距離為兩點間橫縱座標差的絕對值的較大值,我們一般將這種距離叫做切比雪夫距離.其實,笛卡爾座標系上兩點\(P_{1}(x_{1},y_{1}),P_{2}(x_{2},y_{2})\),一共有三種距離,下面一一介紹.
第一種是我們最熟悉的笛卡爾距離,其表示式為\(|P_{1}P_{2}|=\sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}}\)
第二種叫做曼哈頓距離,其表示式為\(|P_{1}P_{2}|=|x_{1}-x_{2}|+|y_{1}-y_{2}|\)
第三種比較少見,叫做切比雪夫距離,即本題要用到的.表示式如下:\(|P_{1}P_{2}|=max(|x_{1}-x_{2}|,|y_{1}-y_{2}|)\)
特別的是,曼哈頓距離和切比雪夫距離可以互相轉換.我們考慮最簡單的情況,在一個二維座標系中,設原點為(0,0)(0,0),如果用曼哈頓距離表示,則與原點距離為11的點會構成一個邊長為11的正方形.
如果用切比雪夫距離表示,則與原點距離為11的點會構成一個邊長為22的正方形
第二個影象是由第一個影象放大兩倍後旋轉45°得到的.根據一堆神奇的性質我們可以\(YY\)
於是乎我們可以將本題轉化為曼哈頓距離,即求\(Max_{i=1}^{n} \{ \sum_{j\not= i}|x_{i}-x_{j}| +\sum_{j\not= i}|y_{i}-y_{j}| \}\),去括號後利用字首和維護,二分查詢答案即可實現\(\Omicron(\log n)\)一次查詢.
code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #define R register #define next MabLcdG #define mod 1 #define debug puts("mlg") #define Mod(x) ((x%mod+mod)%mod) using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; inline ll read(); inline void write(ll x); inline void writesp(ll x); inline void writeln(ll x); const ll maxn=310000; ll n; struct node{ ll x,y; }v[maxn]; ll sx[maxn],sy[maxn],lshx[maxn],lshy[maxn]; ll ans; int main(){ n=read(); for(R ll i=1,x,y;i<=n;i++) x=read(),y=read(),v[i].x=lshx[i]=x+y,v[i].y=lshy[i]=x-y; sort(lshx+1,lshx+n+1); sort(lshy+1,lshy+n+1); for(R ll i=1;i<=n;i++) sx[i]=sx[i-1]+lshx[i],sy[i]=sy[i-1]+lshy[i]; ans=((ull)1<<63)-1; for(R ll i=1;i<=n;i++){ ll x=v[i].x,y=v[i].y; ll res=0; ll pos=lower_bound(lshx+1,lshx+n+1,x)-lshx; res+=pos*x-(n-pos)*x-sx[pos]+sx[n]-sx[pos]; pos=lower_bound(lshy+1,lshy+n+1,y)-lshy; res+=pos*y-(n-pos)*y-sy[pos]+sy[n]-sy[pos]; ans=min(ans,res); } writeln(ans>>1); } inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;} inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');} inline void writesp(ll x){write(x);putchar(' ');} inline void writeln(ll x){write(x);putchar('\n');}