题目描述
给出一个长度为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]的中位数。
输入输出样例
说明
对于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 ",b[ask(1,Size,rt[0],rt[i],i/2+1)]); return 0; }