题解 P1168 【中位数】

看了此题,发现是求中位数,自然而然的想到了求kth

求kth有多种,我用的是权值线段树,即记录x的个数,但,我们看题,发现a[i]可以高达1e9,一个数组是开不完的,

不过万幸的是n只到了1e5,而求kth只需要知道大小关系就行,不需要知道具体的值,所以,我们可以用离散化来搞定它!

这里说一下stable_sort,它其实跟sort差不多,不过区别在于相同元素sort后的值是一样的!所以stable_sort极适合用于离散化

那么问题来了,假如我们用离线算法,各种判断,骚操作,眼花缭乱,本蒟蒻的内心qwq 所以,我们可以考虑在线算法!

我们动态将此时的a[i] (离散化后) 的个数+1,然后每到i为奇数时我们就求出的(i+1)/2大的数即可了~

以下是代码:

#include<bits/stdc++.h>//离散化+权值线段树求kth 
    using namespace std;
    const int N=1e5+1;
    long long a[N];
    long long e[N],b[N];
    int c[N];
    int d[N<<2];
    inline long long read(){
        long long X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }//快读 
    inline bool kk(int x,int y){
        return a[x]<a[y];
    }
    inline void up(int now,int l,int r,int x){
        d[now]++;//范围中有x的都加一,不用左儿子加右儿子那么麻烦~ 
        if(l==r){
            return;
        }
        int mid=((l+r)>>1);
        if(x<=mid){
            up(now<<1,l,mid,x);//向左查找 
            return;
        }
        up(now<<1|1,mid+1,r,x);//向右查找 
    }
    inline int kth(int now,int l,int r,int x){
        if(l==r){
            return l;
        }
        int ls=now*2;
        int mid=((l+r)>>1);
        if(d[ls]>=x){//如果前面的数的个数大于x 
            return kth(ls,l,mid,x);//向前搜 
        }
        return kth(ls|1,mid+1,r,x-d[ls]);//注意这里是x-d[ls],因为前半段有d[ls]个数,那么,kth在后半段的排名应为x-d[ls]
    }
    int main(){
        int n;
        n=read();
        long long x;
        for(int i=1;i<=n;++i){
            a[i]=read();
            e[i]=a[i];//记录存值 
            c[i]=i;//用于之后离散化 
        }
        stable_sort(c+1,c+n+1,kk);//stable排序 
        for(int i=1;i<=n;++i){
            a[c[i]]=i;//离散化值,离散化后a[i]表示原来第i个数第a[i]大
        }
        for(int i=1;i<=n;++i){
            b[a[i]]=e[i];//记录值,用于输出 
        }
        for(int i=1;i<=n;++i){
            up(1,1,1e5,a[i]);//a[i]加一 
            if(i%2){
                int zhong=(i+1)>>1;
                printf("%lld
",b[kth(1,1,1e5,zhong)]);
            } 
        }
        return 0;
    }
原文地址:https://www.cnblogs.com/ThinkofBlank/p/10146207.html