zoukankan      html  css  js  c++  java
  • 题解 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;
        }
  • 相关阅读:
    POJ 2251 Dungeon Master
    HDU 3085 Nightmare Ⅱ
    CodeForces 1060 B Maximum Sum of Digits
    HDU 1166 敌兵布阵(树状数组)
    HDOJ 2050 折线分割平面
    HDU 5879 Cure
    HDU 1878 欧拉回路
    HDU 6225 Little Boxes
    ZOJ 2971 Give Me the Number
    HDU 2680 Choose the best route
  • 原文地址:https://www.cnblogs.com/ThinkofBlank/p/10146207.html
Copyright © 2011-2022 走看看