看了此题,发现是求中位数,自然而然的想到了求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\n",b[kth(1,1,1e5,zhong)]);
            } 
        } return 0;
    }