中位数之中位数「NOIP多校联考 2019」

题意

给出一个长度为n的序列a,首先求出其所有区间的中位数,将这些中位数构成的集合记为S,求S中所有数的中位数。

这里定义的中位数指: 对于m个数,将其从小到大排序后,第(m/2+1)个数即为中位数,例如(10,30,20)的中位数为20,(10,30,20,40)的中位数为30,(10,10,10,20,30)的中位数为10


思路

这道题还是比较巧妙的。(orz \(mhy\),\(zhh\)

我们可以二分答案,这个显然是有单调性的。那么只要求出值不超过枚举的mid的中位数的数量即可。

我们定义数组\(p[i]\)表示前i个数中超过mid的数的数量。

那么每一个符合条件的区间就会满足:\(r-l>2*(p[r]-p[l])\)(超过mid的数的数量没有达到区间总数的一半)

移一下项得到\(r-2*p[r]>l-2*p[l]\)

于是我们就将其转换为一个逆序对问题了,每一次check的时候将i-p[i]插入树状数组中然后统计即可。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {
    #define int long long
    
    const int N=100100;
    
    int n;
    int a[N],p[N],llim=0x3f3f3f3f3f3f,rlim;
    int tree[N<<2];
    
    inline int lowbit (int x) {
        return x&(-x);
    }
    inline void update (int x,int v) {
        for (register int i=x; i<n*4; i+=lowbit(i)) tree[i]+=v;
    }
    inline int query (int x) {
        int res=0;
        for (register int i=x; i; i-=lowbit(i)) res+=tree[i];
        return res;
    }
    inline bool check (int x) {
        int res=0;memset(tree,0,sizeof(tree));
        for (register int i=1; i<=n; ++i) 
            p[i]=p[i-1]+2*(a[i]>x);
//      update(n,1);
        for (register int i=1; i<=n; ++i) {
            update(i-p[i]+2*n,1);
            res+=query(i-p[i]-1+2*n);
        }
        return (res>=n*(n+1)/4);
    }
    
    inline void MAIN () {
        read(n);
        for (register int i=1; i<=n; ++i) {
            read(a[i]),llim=min(llim,a[i]),rlim=max(rlim,a[i]);
        }
        int mid,ans;
        while (llim<=rlim) {
            mid=(llim+rlim)>>1;
            if (check(mid)) rlim=mid-1,ans=mid;
            else llim=mid+1;
        }
        write(ans);
    }
    
    #undef int
}

int main () {
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    Project::MAIN();
}

猜你喜欢

转载自www.cnblogs.com/ilverene/p/11784697.html