杂题集萃[2]


题目描述

小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的子区间中,最大的中位数。

  • 输入

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

题解

二分前缀和

code

#include<iostream>
#include<cstdio>
using namespace std;
const int N=100010;
int n,m,i,j,k,a[N],b[N],t,l,r,mid;
bool f(int k){
    for (int i=1;i<=n;i++) if (a[i]<k) b[i]=-1; else b[i]=1;
    for (int i=1;i<=n;i++) b[i]+=b[i-1];
    int ans=b[m];t=0;
    for (int i=m+1;i<=n;i++){
        t=min(t,b[i-m]);
        ans=max(ans,b[i]-t);
    }
    if (ans>0) return true; 
    else return false;
}
int main(){
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    l=1;r=1000000000;while (l<r){
        mid=(l+r)/2+1;
        if (f(mid)) l=mid; 
        else r=mid-1;
    }
    printf("%d\n",l);
    return 0;
}
优质内容筛选与推荐>>
1、北京外企招聘Share point 2007 开发人员程序员
2、openmp-private
3、嵌套接口
4、初中同学婚礼 & 利物浦大胜
5、在JavaScript中引用类型和值类型的区别


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号