description觀察題目,我們可以知道,題目求的是對於任意的k,使得σ(|xi-xj|+|yi-yj|)>d (1≤i<j≤k),最小的k是多少。為了解開騎士木乃伊事件,久城一彌和布洛瓦警官來到了停屍間。停屍間裡有n具遺體,每具遺體都有乙個座標(x,y)。
由於停屍間的遺體擺放得橫平豎直,我們認為兩具遺體(xi,yi)和(xj,yj)得距離為|xi-xj|+|yi-yj|。
負責停屍間的工人由於需要經常搬運遺體,所以對任意兩具遺體的距離之和特別有印象。
工人們已經記不得每具遺體對應的是什麼人了。但是它們記得,八年前將公尺莉·馬露的遺體搬進停屍間之後,停屍間的任意兩具遺體的距離之和超過了d。
現在給你工人們將n具遺體搬進停屍間的時間順序,請你找出第一具有可能是公尺莉·馬露的遺體。如果不存在這樣的遺體,請輸出-1。
input
第一行兩個整數n,d,意義如題目描述所示。
接下來n行,按照時間順序給出每具遺體的座標,每行兩個整數x,y。
output
輸出一行乙個整數,表示按照時間順序第一具有可能是公尺莉·馬露的遺體的編號。如果不存在這樣的遺體,輸出-1。
sample input
5 10
1 1
2 2
3 3
4 4
5 5
sample output
4 data constraint
10%的資料保證,n≤500.
40%的資料保證,n≤8000.
60%的資料保證,n≤1e5.
另有10%的資料保證,所有遺體的橫座標x都相同。
另有10%的資料保證,x(i)≤x(i+1),且y(i)≤y(i+1)。
100%的資料保證,n≤6×10^5,0≤d≤1e18,0≤x,y≤1e9.
理解題目,可以很容易的知道,若我們前n-1具屍體間的曼哈頓距離之和為f(n-1),則f(n)=f(n-1)+σ(|xi-xn|+|yi-yn|) (1≤i≤n-1)
因此,我們可以知道,對於這樣的函式f(x)必然是乙個單調遞增的函式。
我們重新回頭觀察題目,對於兩個點(xi,yi),(xj,yj),曼哈頓距離 distance=|xi-xj|+|yi-yj|,那麼,我們可以變式為 distance=max(xi,xj)-min(xi,xj)+max(yi,yj)-min(yi,yj)。
而我們再移動一下式子,讓它沒有負號,並消掉一邊的函式符號,過程如下
distance+min(xi,xj)+min(yi,yj)=max(xi,xj)+max(yi,yj)→distance+2×min(xi,xj)+2×min(yi,yj)=max(xi,xj)+min(xi,xj)+max(yi,yj)+min(yi,yj)
經過剛才的過程,我們得到了式子 distance=xi+xj+yi+yj-2×min(xi,xj)-2×min(yi,yj)。
當然,這個式子我們也可以理解成點i,點j以點(0,0)為中轉站,而得到的它們間的曼哈頓距離。
所以,我們就可以得到函式 dis(i,j)=xi+xj+yi+yj-2×min(xi,xj)-2×min(yi,yj)。
使用剛才得到的函式,我們可以將前k個點的任意兩具遺體的距離的和表示成 σdis(i,j) (1≤i<j≤k)。
我們將剛才的函式分成正的和負的兩部分,可以很快發現,我們可以很快的處理出正的部分,例如,對於前k個點,我們在記錄下sum=σ(xi+yi) (1≤i≤k),因為每個點都會和其它(k-1)個點求取距離,所以正的部分應該是 sum×(k-1)。
而負的部分,我們則需進行一下討論。
我們留意一下,可以發現,剛才的函式中,實際上,橫座標和縱座標是分離的,也就是說,它們並不需要一一對應,(xi,yi)與(xj,yj)的距離和(xi,yj)、(xj,yi)的距離是相同的。所以,我們分別研究它們的橫座標x和縱座標y。
首先,我們考慮暴力。對於前k個點,我們可以對它們進行一次排序,然後,對於橫座標的排序中,點i的排名是ri,我們可以知道它的值xi僅僅對後面(k-ri)個點有貢獻,前面的ri-1個點與它比較時,前面點的x值做貢獻。那麼,我們就可以知道,點i所能做的貢獻時 xi×(k-ri),所以,我們可以得到前k個點所作貢獻的大小 σ[xi×(k-ri)] (1≤i≤k)
但是,該方法要不斷重新統計任意兩點間的曼哈頓距離之和,很顯然方法效率並不高, 複雜度達到o(n^2),並且,還要不斷維護乙個有序的數列,因此,並不可取。
根據上面講述過的,函式f(x)具有單調性,其值隨x增大而增大。所以,我們可以考慮不斷求取f(x)的變化值來得到答案。
例如,在正的部分,由於前k個數的和sum=σ(xi+yi) (1≤i≤k),那麼,(k-1)個數的和便是sum=σ(xi+yi) (1≤i≤k-1).
因為,前k個數,正的部分的總和應該是(k-1)sum,也就是(k-1)σ(xi+yi) (1≤i≤k) ,對於前k-1個數,整的部分的總和是 (k-2)σ(xi+yi) (1≤i≤k-1) 。因此,我們做差,(k-1)σ(xi+yi) (1≤i≤k)-(k-2)σ(xi+yi) (1≤i≤k-1)=(k-1)σ(xi+yi) (1≤i≤k-1)+(k-1)(xk+yk)-(k-2)σ(xi+yi) (1≤i≤k-1)=σ(xi+yi) (1≤i≤k-1)+(k-1)(xk+yk).
所以,從前(k-1)個數到前k個數,正的部分的增加的值,是σ(xi+yi) (1≤i≤k-1)+(k-1)(xk+yk)。當然,縱座標y的變化也是同理。
觀察負的部分,我們也尋找它們的變化量。
根據之前的公式 dis(i,j)=xi+xj+yi+yj-2×min(xi,xj)-2×min(yi,yj),很容易想到,我們需要分類討論。
易知,假如當前已經有乙個有序的序列,裡面有(k-1)個數。那麼當我們插入乙個數xk,它當前的排名是rk,那麼,逐漸遞增的序列中,(1~(rk-1))的數都會與xk這個數計算距離,並且,對答案做出貢獻的是前(rk-1)個數。因為在這個序列中,前(rk-1)個數的大小小於xk,所以在取min時前面的數要做出貢獻,而xk不作貢獻。所以,此時負的部分會減少 2σ(xi) (1≤i<k,ri<rk)
另外,在序列中,排名為(rk+1~k)的數,在與xk計算距離時,xk顯然要小於後面的數,因此,xk要做出貢獻。然後,xk產生的貢獻,就是 2×xk×(當前有多少個數大於xk)。
由於負的部分中出現了兩個統計,乙個是統計有多少個數大於xk,另乙個部分是統計小於xk的數的和,我們選擇使用樹狀陣列來解決問題。
當然,選擇線段樹解決問題,答案並不會錯誤,但是由於複雜度的原因,會出現超時的情況。
**如下:
#include
#define ll long long
using namespace std;
const int maxn=600010;
ll ans,d,sum;
int n,x[maxn],y[maxn],rankx[maxn],ranky[maxn],v[maxn];
struct tree
ll getsum(int i,ll s=0)
ll getnum(int i,ll s=0)
ll calcsum(int left,int right)
ll calcnum(int left,int right)
}xt,yt;
inline bool box(int a,int b)
inline bool boy(int a,int b)
int main()
printf("-1");
return
0;}
多一分陪伴少一分孤獨
多一分陪伴,少一分孤獨 慈母手中線,遊子身上衣 臨前密密縫,意恐遲遲歸 誰言寸草心,報得三春暉。從小就熟背 遊子吟 可是其中滋味遲遲也不能真正體會,自從產房接過小侄子的那一刻,我才真正體會到為人父母的滋味,看到它那懵懂的臉盤,胡亂擺動的小手,那張沒有長牙的小嘴,整顆心都被它融化了,從那刻起相信所有的...
每日筆記(一分耕耘,一分收穫)
堆 存放new出來的物件,可被所有執行緒共享,不會存放別的物件引用 string strs newstring 10 棧 存放基本型別 string strs null1.靜態初始化int a 2.動態初始化int a newint 2 a 0 1 a 1 2 3.陣列的預設初始化陣列是引用型別,它...
一分多行列轉換
問題描述 將以下表方式存放的資料 1 cms8000290693 011101251020006862,2 cms8000692449 9011101012510200105,011201251020000015,041101251020000193,3 cms6000320019 01110125...