• 牛客网NOIP赛前集训营-提高组18/9/9 A-中位数


    链接:https://www.nowcoder.com/acm/contest/172/A
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

    小N得到了一个非常神奇的序列A。这个序列长度为N,下标从1开始。A的一个子区间对应一个序列,可以由数对[l,r]表示,代表A[l], A[l + 1], ..., A[r]这段数。对于一个序列B[1], B[2], ..., B[k],定义B的中位数如下:
    1. 先对B排序。得到新的序列C。
    2. 假如k是奇数,那么中位数为。假如k为偶数,中位数为
    对于A的所有的子区间,小N可以知道它们对应的中位数。现在小N想知道,所有长度>=Len的子区间中,中位数最大可以是多少。

    输入描述:

    第一行输入两个数N,Len。
    第二行输入序列A,第i个数代表A[i]。

    输出描述:

    一行一个整数,代表所有长度>=Len的子区间中,最大的中位数。
    示例1

    输入

    复制
    11 3
    4864 8684 9511 8557 1122 1234 953 9819 101 1137 1759 

    输出

    复制
    8684

    备注:

    数据范围:
    30%: n <= 200
    60%: n <= 2000
    另外有20%:不超过50个不同的数
    100%:1<=Len<=n<=10^5, 1 <= a[i] <= 10^9

    思路:

    表示考场上一看到这道题就一脸懵逼

    于是交了一发主席树(当然不是正解)

    听完讲评才发现二分水过。。。

    其实很简单

    先输进来

    然后开个新数组去重,从小到大排序

    然后就可以二分了

    我们每次二分出一个答案

    判断一下

    怎么判断呢?

    我们先O(n)扫一遍

    x[i]大于等于这个答案话,就赋值为1

    否则为-1

    然后跑前缀和

    再从len开始枚举

    在枚举时维护一个最小前缀和(当前位置的前缀和-最小前缀和=最大前缀和)

    如果最大前缀和>0,就是满足的(看题,这就说明它可以是从小到大第k/2位)

    反之就不满足

    OK

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define rii register int i
    #define rij register int j
    using namespace std;
    int qzh[100005],x[100005],y[100005],z[100005],n,len;
    bool check(int bh)
    {
        int ltt=z[bh];
        int minx=192690817;
        memset(qzh,0,sizeof(qzh));
        for(rii=1;i<=n;i++)
        {
            if(x[i]>=ltt)
            {
                qzh[i]=1;
            }
            if(x[i]<ltt)
            {
                qzh[i]=-1;
            }
            if(i>=len)
            {
                minx=min(minx,qzh[i-len]);
            }
            qzh[i]+=qzh[i-1];
            if(i>=len)
            {
                if(qzh[i]-minx>0)
                {
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        cin>>n>>len;
        for(rii=1;i<=n;i++)
        {
            scanf("%d",&x[i]);
            y[i]=x[i];
        }
        sort(y+1,y+n+1);
        int pre=0;
        for(rii=1;i<=n;i++)
        {
            if(y[i]==z[pre])
            {
                continue;
            }
            pre++;
            z[pre]=y[i];
        }
    //    for(rii=1;i<=pre;i++)
    //    {
    //        cout<<z[i]<<" ";
    //    }
        int l=1,r=pre;
        while(l!=r)
        {
            if(r-l==1)
            {
                if(check(r)==1)
                {
                    l=r;
                }
                else
                {
                    r=l;
                }
                break;
            }
            int mid=(l+r)/2;
            if(check(mid)==1)
            {
                l=mid;
            }
            else
            {
                r=mid;
            }
        }
        cout<<z[r];
    }
  • 相关阅读:
    247. Strobogrammatic Number II 倒过来看也一样的数
    性能测试结果分析
    性能测试文档
    性能测试技术
    性能测试流程
    JMeter(7)插件
    Java同步工具类
    线程池
    死锁
    Lock显示锁
  • 原文地址:https://www.cnblogs.com/ztz11/p/9614112.html
Copyright © 2020-2023  润新知