zoukankan      html  css  js  c++  java
  • AtCoder 4351 Median of Medians(二分+树状数组)

    题意:给你列数,有一个中位数的定义,然后求出每一个区间的中位数,然后打印这些中位数的中位数

    思路:没见过,真的学不来,看了聚聚们的博客以后,才学会。我们直接二分答案,我们有了答案以后,小于等于的mid的标记为1,其他的为-1,这样从一定程度上反应了区间大于和小于中位数的个数,对这个数组求前缀和,这样的话,我们变成了这样一个问题,我们如果找到一个正序数的一对数,这样这个区间的中位数就大于mid,这样的话,我们一直二分,会收敛到最后的中位数,因为二分是只需要判断能不能可行,不需要考虑答案是几,附一篇聚聚的博客(传送门

    (chaoxi)代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn=1e5+10;
    int a[maxn];
    int n;
    int c[maxn*15];
    int pre[maxn*15];
    int lowbit(int x)
    {
        return x&-x;
    }
    void add(int x)
    {
        for(int i=x;i<=2*maxn;i+=lowbit(i))c[i]++;
    }
    LL query(int x)
    {
        LL res=0;
        for(int i=x;i>0;i-=lowbit(i))res+=c[i];
        return res;
    }
    
    bool check(int x)
    {
        memset(c,0,sizeof(c));
        pre[0]=0;
        for(int i=1;i<=n;i++)pre[i]=pre[i-1]+(a[i]>=x?1:-1);
        LL res=0;
        for(int i=0;i<=n;i++){
            res+=query(pre[i]+maxn);
            add(pre[i]+maxn);
        }
        return res>=1LL*n*(n+1)/4;
    }
    
    int main()
    {
        n=read();
        int L=0,R=0,ans=0;
        for(int i=1;i<=n;i++){
            a[i]=read();
            R=max(R,a[i]);
        }
        while(L<=R){
            int mid=(L+R)>>1;
            if(check(mid)){
                L=mid+1;ans=mid;
            }
            else{
                R=mid-1;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    jQuery的动画效果
    jQuery的event事件
    设计模式 命令行模式
    桥接模式
    享元模式
    代理模式
    门面模式
    代理模式
    python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod
    库存负数
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9917795.html
Copyright © 2011-2022 走看看