中位数
Posted oieredsion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中位数相关的知识,希望对你有一定的参考价值。
问题
C得到了一个非常神奇的序列A。这个序列长度为N,下标从1开始。A的一个
子区间对应一个序列,可以由数对[l,r]表示,代表A[l], A[l + 1], ..., A[r]这段数。
对于一个序列B[1], B[2], ..., B[k],定义B的中位数如下:
- 先对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;
}
以上是关于中位数的主要内容,如果未能解决你的问题,请参考以下文章