洛谷 P1168 中位數
阿新 • • 發佈:2017-11-19
upd 輸入格式 div show median for 所有 clas clu
題目描述
給出一個長度為N的非負整數序列A[i],對於所有1 ≤ k ≤ (N + 1) / 2,輸出A[1], A[3], …, A[2k - 1]的中位數。即前1,3,5,……個數的中位數。
輸入輸出格式
輸入格式:
輸入文件median.in的第1行為一個正整數N,表示了序列長度。
第2行包含N個非負整數A[i] (A[i] ≤ 10^9)。
輸出格式:
輸出文件median.out包含(N + 1) / 2行,第i行為A[1], A[3], …, A[2i – 1]的中位數。
輸入輸出樣例
輸入樣例#1:7 1 3 5 7 9 11 6輸出樣例#1:
1 3 5 6
說明
對於20%的數據,N ≤ 100;
對於40%的數據,N ≤ 3000;
對於100%的數據,N ≤ 100000。
主席樹
題目鏈接
#include <algorithm> #include <cstdio> #define N 100005 using namespace std; int n,tot,Size,a[N],b[N],rt[N],ls[N*30],rs[N*30],sum[N*30]; int build(int l,int r) { int now=++tot; sum[now]=0; if(l==r) return now; int mid=(l+r)>>1; ls[now]=build(l,mid); rs[now]=build(mid+1,r); return now; } int rank(int x) {return lower_bound(b+1,b+1+Size,x)-b;} void update(int l,int r,int x,int &y,int t) { y=++tot; sum[y]=sum[x]+1; if(l==r) return; ls[y]=ls[x]; rs[y]=rs[x]; int mid=(l+r)>>1;if(t<=mid) update(l,mid,ls[x],ls[y],t); else update(mid+1,r,rs[x],rs[y],t); } int ask(int l,int r,int x,int y,int k) { if(l==r) return l; int mid=(l+r)>>1; if(sum[ls[y]]-sum[ls[x]]>=k) return ask(l,mid,ls[x],ls[y],k); else {k-=sum[ls[y]]-sum[ls[x]];return ask(mid+1,r,rs[x],rs[y],k);} } int main(int argc,char *argv[]) { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+1+n); Size=unique(b+1,b+1+n)-b-1; rt[0]=build(1,Size); for(int i=1;i<=n;++i) update(1,Size,rt[i-1],rt[i],rank(a[i])); for(int i=1;i<=n;i+=2) printf("%d\n",b[ask(1,Size,rt[0],rt[i],i/2+1)]); return 0; }
洛谷 P1168 中位數