码迷,mamicode.com
首页 > 其他好文 > 详细

中位数

时间:2019-11-10 00:00:32      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:pre   思考   偶数   pos   return   是什么   out   利用   中位数   

问题
C得到了一个非常神奇的序列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的子区间中,中位数最大可以是多少。

解:
网上找到的题目 觉得很好就记下来了
首先二分答案的题目满足的性质一定是单调性
不一定是最小值最大或者最大值最小
当我们对于答案没有思路的时候不妨逆向思考利用二分答案增加条件
此题便是如此
首先直接暴力似乎不可做 并且答案也不好求 这让我想起了CF上的一道题 也是求中位数并且利用了二分答案
正着不好思考 答案似乎太难求
假如二分答案的话 似乎大于的都可以标为1 小于的话都可以标为-1 因为数值并不产生影响我们只会关心大小关系 调大mid 显然合法的区间会变小 调大mid合法的区间会变大 满足单调性 我们考虑二分答案
那一个区间的合法条件是什么呢???
区间的和>0 代表存在一个序列 使得 中位数>mid 假如我们调大mid 存在性就会越来越小 换句话说我们只要逼近二分的答案 就能出解

code:

//
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define maxnn 200100
ll n,LEN;
ll a[maxnn];
ll b[maxnn];
ll sum[maxnn];
bool isok(ll mid)
{
    ll pos=0,ans=1111111000000;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>=mid) b[i]=1;
        else b[i]=-1;
    }
    for(int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]+b[i];
        while(pos<=i-LEN)
        {
            ans=min(ans,sum[pos]);
            pos++;
        }
        if(i>=LEN)
        if(sum[i]-ans>0) return true;
    }
    return false;
}
int main()
{
    scanf("%lld%lld",&n,&LEN);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }   
    ll l=0,r=100000000000;
    while(l<=r)
    {
        ll mid=(l+r)/2;
        if(isok(mid))
        {
            l=mid+1;
        }
        else
        {
            r=mid-1;
        }
    }
    cout<<r;
}

中位数

标签:pre   思考   偶数   pos   return   是什么   out   利用   中位数   

原文地址:https://www.cnblogs.com/OIEREDSION/p/11828047.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!