1. 程式人生 > >【切比雪夫距離轉曼哈頓距離】棋盤問題

【切比雪夫距離轉曼哈頓距離】棋盤問題

【題目描述】 
小O 對國際象棋有著濃厚的興趣,因為他水平高超,每次人機對戰他總是輕鬆獲勝,所
以他決定自己跟自己下國際象棋。 
小O 的棋盤非常大,達到了 10^9*10^9,現在他在棋盤上擺放了 n 個國王,並對你提出
了q次詢問,每次詢問指定一個座標,問將所有國王從初始位置全部移動到這個座標所需要
的最小步數是多少,詢問之間相互獨立,也就是說每次詢問結束後國王會全部回到原來位置。  
注意:由於小 O擔心大家無法理解過於高深的規則,所以在本題中,國王之間不會發生
相互攻擊而且多個國王可以同時處在一個格子中, 國際象棋中國王一步只能移動到與其八
連通的格子中。 
【輸入格式】 
第一行一個正整數 T表示資料組數。 
對於每組資料,共有(n+q+1)行: 
第一行兩個數字 n,q分別表示國王數量和詢問數量。 
接下來n行,每行兩個數字 Kxi,Kyi表示國王所在座標。 
接下來q行,每行兩個數字 Txi,Tyi表示目標座標。 
【輸出格式】 
對於每組資料,輸出共有q行,每行一個整數表示對應詢問的答案。 
【輸入樣例】 

1 1 
233 666 
666 233 
【輸出樣例】 
433 
【資料範圍】 

N<=1000000,Q<=1000000,
本題共7個測試點,不採用 subtask評測,但每個測試點分值不同. 
資料範圍中的 X,Y範圍表示Kxi,Kyi,Txi,Tyi的範圍,未標註即為沒有特殊限制 
對於全部資料,滿足 N的總和不超過10^6 且Q 的總和不超過10^6,輸入檔案中所有數
字均為正整數且不超過 10^9. 
#1:1pt,滿足T=n=q=X=Y=1; 
#2:3pts,滿足 T=1,1<=X,Y<=5,1<=n<=5,q=1; 
#3:16pts,滿足 T=1,1<=X,Y<=5,1<=n<=5; 
#4:11pts,滿足 T=1,1<=X,Y<=1000,1<=n,q<=5000; 
#5:21pts,滿足所有資料中 N*Q的總和不超過 5*10^7; 
#6:22pts,滿足 T=1,1<=X,Y<=1000; 
#7:26pts,無特殊限制。 

關於切比雪夫距離和曼哈頓距離

這道題其實就是求所有點到一個點的切比雪夫距離之和。我們把它轉化成曼哈頓距離就行了。

具體見程式碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=1e6+233;
inline void read(ll &x){
	x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
}
ll x[maxn],y[maxn];
ll sumx[maxn],sumy[maxn];
ll n,q,T,X,Y,tx,ty;
ll ans;
int main(){
	read(T);
	while(T--){
		read(n),read(q);
		for(ll i=1;i<=n;++i) read(tx),read(ty),x[i]=tx+ty,y[i]=tx-ty;
        //轉化座標
		sort(x+1,x+1+n),sort(y+1,y+1+n);
        //座標排序
		for(ll i=1;i<=n;++i) sumx[i]=sumx[i-1]+x[i],sumy[i]=sumy[i-1]+y[i];
		//座標字首和
		for(ll i=1;i<=q;++i){
			ll ans=0;
			read(tx),read(ty);
			X=tx+ty,Y=tx-ty;
			ll pos=lower_bound(x+1,x+n+1,X)-x;
			ans+=(pos-1)*X-sumx[pos-1]+sumx[n]-sumx[pos-1]-(n-pos+1)*X;
				pos=lower_bound(y+1,y+n+1,Y)-y;
			ans+=(pos-1)*Y-sumy[pos-1]+sumy[n]-sumy[pos-1]-(n-pos+1)*Y;
			printf("%lld\n",ans/2);
		}
	}
}

其中橫座標的曼哈頓距離和縱座標的曼哈頓距離是類似的,也是獨立的。下面拿橫座標的舉個梨子把。

我們要求的就是Σ|x[i]-X|。x[1]到x[pos-1]是小於X的,絕對值拆開就是X-x[i],後面的就是x[i]-X。Y同理。