洛谷 P1168 中位数

题目描述

给出一个长度为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
",b[ask(1,Size,rt[0],rt[i],i/2+1)]);
    return 0;
}
原文地址:https://www.cnblogs.com/sy1in/p/7859730.html