2014-03-08 09:47:04Morris
[其他題目][二分答案] 差值中位數
Description
有 n 個整數,則任兩個數字有一個差值 (取絕對值)。因此會有 C(n, 2) 個差值,求這 C(n, 2) 個整數的中位數。
Input Format
第一行有一個正整數 T,代表有幾組測試資料。
每組測資第一行有一個正整數 n (n < 100,000),
接著第二行有 n 個正整數 A[i] (0 < A[i] < 1,000,000,000)。
接著第二行有 n 個正整數 A[i] (0 < A[i] < 1,000,000,000)。
Output Format
每筆測資請輸出一行,包含一個整數,代表差距中的中位數。
若 C(n, 2) 是偶數,則輸出較大的那一個。
Sample Input
2 4 1 3 5 8 3 1 2 3
Sample Output
4 1
題目解法:
先對輸入做排序,然後二分答案(最後的中位數)檢查這個整數,坐落於排名第幾,試圖推到中位數的位置。
檢查的方式 =>
對於每一個數字 x,找到 upper_bound(x+guess_number) 的位置,找到與 x 可以湊出差值小於等於 guess_number 的個數。
效率 O(n log^2 n )
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#define oo 1000000000
using namespace std;
int A[100001], flag;
int cmp(const void *i, const void *j) {
return *(int *)i - *(int *)j;
}
int Find_Median(long long n) {
long long Gap = n*(n-1)/2, tmp1, tmp2;
int l = 0, m, r = oo, i, flag = 0;
int idx;
Gap = Gap/2 + 1;
do {
m = (l + r)/2, tmp1 = 0, tmp2 = 0, flag = 0;
idx = 0;
for(i = 0; i < n; i++) {
while(idx < n && A[idx]-A[i] <= m) {
if(A[idx]-A[i] == m) flag = 1;
idx++;
}
tmp1 += idx - i - 1;
}
if(flag) {
idx = 0;
for(i = 0; i < n; i++) {
while(idx < n && A[idx]-A[i] < m)
idx++;
tmp2 += idx - i - 1;
}
}
if(tmp1 >= Gap && tmp2 < Gap && flag != 0) return m;
if(tmp1 < Gap) l = m+1;
else r = m-1;
} while(l <= r);
}
int main() {
int i, j, n, k = 0;
int testcase;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%d", &A[i]);
sort(A, A+n);
printf("%d\n", Find_Median(n));
}
return 0;
}
上一篇:[高演][攤銷] 資料結構