題目內容
tt 是一位重度愛貓人士,每日沉溺於 b 站上的貓咪頻道。
有一天,tt 的好友 zjm 決定交給 tt 乙個難題,如果 tt 能夠解決這個難題,zjm 就會買乙隻可愛貓咪送給 tt。
任務內容是,給定乙個 n 個數的陣列 cat[i],並用這個陣列生成乙個新陣列 ans[i]。新陣列定義為對於任意的 i, j 且 i != j,均有 ans = abs(cat[i] - cat[j]),1 <= i < j <= n。試求出這個新陣列的中位數,中位數即為排序之後 (len+1)/2 位置對應的數字,』/』 為下取整。
tt 非常想得到那只可愛的貓咪,你能幫幫他嗎?
輸入格式
多組輸入,每次輸入乙個 n,表示有 n 個數,之後輸入乙個長度為 n 的序列 cat, cat[i] <= 1e9 , 3 <= n <= 1e5。
輸出格式
輸出新陣列 ans 的中位數。
輸入示例
4輸出示例1 3 2 4
31 10 2
1解題思路顯然如果我是tt的話我就會放棄這只貓。8
哎,中位數嘛,如果能把n的範圍縮小一點那這道題將可以直接暴力演算法絕殺,可惜換不得。
所以怎麼二分呢?
對於一串數字,我們在已知這串數字的數量n的情況下,可以很容易地求得其中位數所在的位置為(n+1)>>1。
那麼如果我們反著來看呢?
很明顯我們即便不把ans陣列直接算出來,也可以提前預判到其中位數所在的位置應該是((n * (n - 1)) / 2 + 1) / 2,此處n為cat陣列的大小。
因此我們就可以繼續分析:
已知了中位數的位置,我們只需要對ans進行二分:
那麼對於某乙個ans中的數p,
只需要求出小於等於它的數的個數就行了,這個個數如果等於中位數應該擁有的個數,那就說明p是中位數。
當然了,如果p比中位數少或者多,所以二分就行了。
但是既然用到了二分,那麼我們就需要必要條件:被二分的陣列應該是單調的。
看看題目:ans = abs(cat[i] - cat[j])
我們如何才能把絕對值化掉呢?
顯然只需要保證cat[i]大於cat[j]就可以了。
我們可以提前對cat進行排列,然後保證i大於j就行了。
因此此時的式子變成了:p>=cat[i]-cat[j],其中i>j。
把cat[j]挪到式子左邊:p+cat[j]>=cat[i]。
對於某個二分出來的p,我們只需要固定j,然後二分i就行了,這樣就可以求出所有滿足此式子的i和j的對數,即ans陣列裡小於等於p的數的個數。
複雜度為o(logk+nlogn),可以接受。
於是有**:
#include
#include
#include
#include
using
namespace std;
vector<
int>cat;
int n;
bool
cmp(
const
int& a,
const
int& b)
intfun
(int
&mid,
const
int&rank)
else r = mid2 -1;
}if(ans !=-1
) currank +
= ans - i;}if
(currank < rank)
return1;
//小於
if(currank >= rank)
return2;
//大於等於
}int
main()
sort
(cat.
begin()
, cat.
end(
), cmp)
;int rank =
((n *
(n -1)
)/2+
1)/2
;//中位數的名次
int l =
0, r = cat.
back()
- cat.
front()
,ans=-1
;while
(l <= r)
else
if(opnum ==1)
}if(ans !=-1
) cout << ans << endl;
}}
如果使用iostream,顯然不要忘記使用
ios::
sync_with_stdio
(false);
cin.
tie(0)
;
血的教訓
C 二分法查詢,遞迴二分法
用二分法來求需要查詢的值.includeusing namespace std 查詢key元素是否存在 int findkey const int buf 100 const int ilen,const int key else right left mid 1 查詢失敗 return 1 查詢k...
python二分法查詢 Python 二分法查詢
二分法查詢主要的作用就是查詢元素 lst 1,3,5,7,12,36,68,79 資料集 百萬級資料 num int input 請輸入你要查詢的元素資訊 for el in lst if num el print 存在 break else print 不存在 len lst 0 1 2 3 4 ...
TT的神秘禮物 Week4作業C題
給定乙個 n 個數的陣列 cat i 並用這個陣列生成乙個新陣列 ans i 新陣列定義為對於任意的 i,j 且 i j,均有 ans abs cat i cat j 1 i j n。試求出這個新陣列的中位數,中位數即為排序之後 len 1 2 位置對應的數字,為下取整。輸入 多組輸入,每次輸入乙個...