不知道已經成爲大學生的你是否還記得中位數這個東西,我們似乎很少再用到它,今天 就想讓你做一下這個小學數學題。
初始你手裏什麼也沒有,接下來 會按順序給你 個數。當你手中的數的個數爲奇數時,你需要告訴 你手裏這堆數的中位數是多少。
輸入格式
第一行一個正整數 ,表示給你的數的個數。
接下來一行 個整數,表示依次給你的這些數 。
輸出格式
輸出 行,每行一個整數,表示答案。
當 爲奇數時 ,當 爲偶數時 ,其中除法爲下取整。
樣例
樣例輸入1
5
1 2 3 4 5
樣例輸出1
1
2
3
樣例輸入2
6
4 9 1 2 7 -66666
樣例輸出2
4
4
4
數據範圍與提示
本題Idea來自2018年暑期集訓期間與 的交流
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define MN 200005
int n,m,a[MN],v[MN],id[MN],l,r,k,root[MN],cnt;
//a:輸入的數 id:離散化的編號 root:各個歷史版本的根
struct tree{
int Ls,Rs,sum;
}Tree[MN*20];
//Ls、Rs:左右子樹 sum:區間中數的數量
void change(int num,int &x,int l,int r){//注意這個'&'
Tree[cnt]=Tree[x];x=cnt;cnt++;
//建一個新節點,以便修改
Tree[x].sum++;
if(l==r) return;
if(id[mid]>=num) change(num,Tree[x].Ls,l,mid);
else change(num,Tree[x].Rs,mid+1,r);
//改變需要改變的子節點
}
int ask(int i,int j,int num,int l,int r){
if(l==r) return l;
int tmp=Tree[Tree[j].Ls].sum-Tree[Tree[i].Ls].sum;
if(tmp>=num) return ask(Tree[i].Ls,Tree[j].Ls,num,l,mid);
else return ask(Tree[i].Rs,Tree[j].Rs,num-tmp,mid+1,r);
}//差分後查詢
int main(){
scanf("%d",&n);
cnt=1;
for(int i=1;i<=n;i++) {scanf("%d",&a[i]);v[i]=a[i];}
sort(a+1,a+1+n);
int N=unique(a+1,a+1+n)-a-1;
for(int i=1;i<=N;i++)
id[i]=a[i];
//離散化
for(int i=1;i<=n;i++){
root[i]=root[i-1];//要共用上一個版本的節點
change(v[i],root[i],1,N);
}
for(int i=1;i<=n;i+=2){
printf("%d\n",id[ask(root[0],root[i],i/2+1,1,N)]);
}
return 0;
}