• 牛客 NOIp模拟1 T1 中位数 解题报告


    中位数

    题目描述

    (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)是奇数,那么中位数为(C[frac{k+1}{2}])。假如(k)为偶数,中位数为(C[frac{k}{2}])
      对于(A)的所有的子区间,小(N)可以知道它们对应的中位数。现在小(N)想知道,所有长度(>=Len)的子区间中,中位数最大可以是多少。

    输入描述:

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

    输出描述:

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

    备注:

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


    话说本来写二分,但是被问了,为什么有单调性啊,大的成为中位数小的不一定啊

    然后给迷住了

    事实上,我们二分答案,得到的不是”答案大于它还是小于它“这样一个东西吗,而不是”它是否可以成为答案“,而且本来就是在求最大值娅

    二分以后,把>=的置1,<的置-1

    然后我们判断有没有一个长度大于len的区间大于0就可以了

    处理前缀和最小值,扫描前缀和就可以了


    Code:

    #include <cstdio>
    #include <algorithm>
    const int N=1e5+10;
    int a[N],b[N],f[N],n,len;
    int min(int x,int y){return x<y?x:y;}
    bool check(int p)
    {
        for(int i=1;i<=n;i++) f[i]=(a[i]>=p?1:-1)+f[i-1];
        for(int mi=0,i=len;i<=n;i++)
        {
            mi=min(mi,f[i-len]);
            if(f[i]>mi) return true;
        }
        return false;
    }
    int main()
    {
        scanf("%d%d",&n,&len);
        for(int i=1;i<=n;i++) scanf("%d",a+i),b[i]=a[i];
        std::sort(b+1,b+1+n);
        int m=std::unique(b+1,b+1+n)-b-1;
        for(int i=1;i<=n;i++)
            a[i]=std::lower_bound(b+1,b+1+m,a[i])-b;
        int l=1,r=m;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if(check(mid))
                l=mid;
            else
                r=mid-1;
        }
        printf("%d
    ",b[l]);
        return 0;
    }
    

    2018.9.9

  • 相关阅读:
    coder的脚印
    Mysql
    MSDos
    Windows Develop
    Eclipse 使用总结
    DBA常用SQL
    SSH总结
    Unity3D协程
    yield的作用
    UGUI优化
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9614533.html
Copyright © 2020-2023  润新知