給出長度n(n<=100000) 的非負整數序列ai,求出前1,3,5…個數的中位數
正規的做法有用stl的優先佇列,維護乙個大根堆和乙個小根堆,構造乙個元素數量平衡的t1-r-t2結構。其中b是中位數,a1的所有值都小於r,並且用大根堆的性質表示出其內最大的元素,以方便在插入新的值時決定要如何插入。a2是值都大於等於r的小根堆,理由同上
但是
,本著殺雞用牛刀的原則(抄板子),這個題還可以用名次樹來完成,n次插入,大約n/2次查詢名次,仍然是o(n
logn
)o(nlogn)
o(nlog
n)的級別,在1e5的情況下可行!
中位數即查詢排名n/2+1位次的數(n=1,3,5…)
用了p3369的板子
read()函式可以讀入乙個數字
insert(a,root)是插入數a
erase(a,root)刪除數a,有多個只刪除乙個
rank(a,root)返回a的名次
find(a,root)返回名次a的數
最後兩者結合可以找到後繼/前驅
本題只用到了insert和find
#include
"cstdlib"
#include
"iostream"
#include
"cstdio"
#include
"cstring"
#include
//佇列
#define update( cur ) if(cur-> left-> size)cur-> size = cur -> left->size + cur -> right -> size , cur -> value = cur -> right -> value
#define new_node( s , v , a , b ) ( & ( * st [ cnt++ ] = node ( s , v , a , b) ) )
#define merge( a , b ) new_node( a -> size + b -> size , b -> value , a , b )
#define ratio 4
int n, cnt, s, a;
inline
intread()
while
(isdigit
(ch)
) x = x *
10+ ch -
'0', ch =
getchar()
;return x * v;
}class
node
node()
};node* root,
* st[
300010
], t[
300010],
* null,
* father;
inline
void
maintain
(register node* cur)
intfind
(int x, node* cur)
intrank
(int x, node* cur)
void
insert
(int x, node* cur)
void
erase
(int x, node* cur)
//main之前都是板子內容
intmain()
return0;
}
洛谷 P1168 中位數
題目描述 給出乙個長度為n的非負整數序列a i 對於所有1 k n 1 2,輸出a 1 a 2 a 2k 1 的中位數。color red 即 color 前1,3,5,個數的中位數。輸入輸出格式 輸入格式 輸入檔案median.in的第1行為乙個正整數n,表示了序列長度。第2行包含n個非負整數a ...
洛谷 P1168 中位數
這個題很簡單 但是我要講3種做法 我們維護乙個小根堆乙個大根堆,其中大根堆的堆頂小於小根堆的所有元素,待加入元素大於大根堆堆頂元素就加入小根堆,反之加入大根堆,然後維護兩個堆元素數量,使得兩個堆的元素數量差為1,這樣我們取兩個堆中元素多的那個的堆頂就是答案 初始化的時候先往大根堆裡加入乙個元素,避免...
洛谷 P1168 中位數
給出乙個長度為n的非負整數序列a i 對於所有1 k n 1 2,輸出a 1 a 3 a 2k 1 的中位數。color red 即 color 前1,3,5,個數的中位數。輸入格式 輸入檔案median.in的第1行為乙個正整數n,表示了序列長度。第2行包含n個非負整數a i a i 10 9 輸...