【問題描述】
給出 n 個整數:x1, x2, ... , xn,定義f(i,j)=∣xi - xj∣ (1 ≤ i < j ≤ n),於是我們可以得到c(n,2)個f(i,j)。
你的任務是找出這c(n,2)個f(i,j)中第k小的數(把f(i,j)由小到大排序後的第k個數)。
【輸入格式】
包含多組測試資料,每組資料佔兩行,第一行為整數n 和 k,第二行包含n個整數,表示x1, x2, ... , xn, ( xi ≤ 1,000,000,000 3 ≤ n ≤ 100,000 )
【輸出格式】
對於每組資料,輸出一行乙個整數,表示第k小的數。
【輸入樣例】
4 31 3 2 4
3 21 10 2
【輸出樣例】 18
【樣例解釋】
樣例中的第一組資料:1 3 2 4,得到f(i,j)序列為:2 1 3 1 1 2,其中第3小的是1。
【資料範圍】
|xi| ≤ 1,000,000,000 , 3 ≤ n ≤ 1,00,000 , 1 ≤ k ≤ c(n,2)
【**】
poj 3579改編
解題思路:根據題意,最簡單的想法就是直接把f(i,j)生成出來,由小到大排序,輸出第k小的數即可,但本題的資料規模太大,直接生成f(i,j)必然不行。本題的高效演算法為二分猜答案,難點同樣在於如何判斷猜的答案是否可行,判斷時主要是通過找出小於等於m(猜的答案)的f(i,j)數目,判斷它與k的大小即可。我們可以先將輸入的數由小到大排序,這樣f(i,j)=∣xi - xj∣就可以去掉絕對值,即f(i,j)=xj-xi(因為j>i),然後列舉x[j],每列舉乙個x[j],二分查詢大於等於xj-m的第乙個元素下標t(因為f(i,j)<=m,即xj-xi<=m,可以轉化為xi>=xj-m),則此時小於等於m的f(i,j)的個數就要加上j-t,最後如果數目大於等於k,則說明m是第k小或大於第k小的,那麼答案可以再小些,如果數目小於k,則說明m是小於第k小的,那麼答案就要再大些。需要注意的是,輸入時的k和計算f(i,j)的數目都可能超出int範圍,應定義為long long。
#include#include#include#include#includeusing namespace std;
const int maxn=100005;
int n;
long long k;
int x[maxn];
bool check(int m) //判斷答案是否可行
if(sum>=k) return 1;
return 0;
}int main()
printf("%d\n",ans);
} return 0;
}
二分 基於第K大數的思考 poj3579
最近在用二分解決一些的問題的時候,發現有一類問題 求出乙個未知的序列的第k個數,這類問題對於二分邊界的處理上存在不同的理解.於是本文就這類問題進行 給出n個數的陣列a,用這n個數每兩個作差,將差值的絕對值作為乙個新的陣列b.這個陣列有c n,2 n n 1 2個元素.找出b陣列中的中位數.同時n的範...
Poj3579Median二分查詢第K大
題目鏈結 題目 給定一組數x ix i xi 我們可以得到c n 2 c n,2 c n,2 個差值 xi xj i x i x j i j xi x j i,問求這些差值組成的數列中第k kk個 k c n,2 2 k c n,2 2 k c n 2 2 是多少。思路比較常見的二分題目。首先對輸入...
第k小因子
題目 給定乙個數 n,1 n 10 15,求第k小因子。假設10 8次執行時間為1s。這道題我相信大家都能夠想到o n 的解決方法,但是考慮到時間複雜度,如果乙個數為10 15次方,這將是乙個很大的計算時間,因此o n 不可取。接下來提供乙個 o n 1 2 的方法,其實也很簡單,就是只遍歷 sqr...