链接:https://www.nowcoder.com/acm/contest/172/A
来源:牛客网
题目描述
小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
二分答案x,把大于等于x的记为1,否则记为-1,计算长度大于等于L的最大字段和,若其大于0,则存在。
#include<iostream>
#include<algorithm>
#include<cstring>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=100005;
int n,L;
int a[MAXN],b[MAXN],c[MAXN];
bool check(int x)
{
int i,j;
f(i,1,n){
if(a[i]<b[x]){
c[i]=-1;
}
else c[i]=1;
c[i]+=c[i-1];
}
int las=0,ans=c[L];
f(i,L+1,n){
las=min(las,c[i-L]);
ans=max(ans,c[i]-las);
if(ans>0) return true;
}
return false;
}
int main()
{
int i,j;
int l,r;
cin>>n>>L;
f(i,1,n){
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
l=1;r=n;
while(l<r){
int mid=(l+r+1)>>1;
if(check(mid)){
l=mid;
}
else r=mid-1;
}
cout<<b[l]<<endl;
return 0;
}