题目描述
You are a given an array a of length n. Find a subarray a[l…r] with length at least k with the largest median.
A median in an array of length n is an element which occupies position number ⌊n+12⌋ after we sort the elements in non-decreasing order. For example: median([1,2,3,4])=2, median([3,2,1])=2, median([2,1,2,1])=1.
Subarray a[l…r] is a contiguous part of the array a, i. e. the array al,al+1,…,ar for some 1≤l≤r≤n, its length is r−l+1.
Input
The first line contains two integers n and k (1≤k≤n≤2⋅105).
The second line contains n integers a1,a2,…,an (1≤ai≤n).
Output
Output one integer m — the maximum median you can get.
Examples
input
5 3
1 2 3 2 1
output
2
input
4 2
1 2 3 4
output
3
Note
In the first example all the possible subarrays are [1…3], [1…4], [1…5], [2…4], [2…5] and [3…5] and the median for all of them is 2, so the maximum possible median is 2 too.
In the second example median([3…4])=3.
题目大意
给出一个序列a[],求a[]中长度大于等于k的子序列的中位数的最大值。
本题中一个序列中位数的求法:先将这个序列进行升序排序,然后取中位数。
题目分析
这里有一个技巧:对于这种需要对大量的区间排序但却只会用到这段区间中的一个数的情况。我们可以二分答案,并在check函数中将a[]中小于mid的数变为-1(或0),而大于等于mid的数变为1。然后再根据具体问题进行求解。
在这个题中我们只需要再对a[]进行前缀和处理,然后对于一段区间[l,r],只要a[r]-a[l-1]>=1,那么这段区间的中位数就是大于等于mid的,既符合要求。
通过这种方式即可找出最终答案。
代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
#include <algorithm>
#define LL long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=2e5+5,INF=0x3f3f3f3f;
int n,k,a[N];
int b[N],minx[N];
bool check(int x)
{
for(int i=1;i<=n;i++) //用b[i]记录a[i]变得值
if(a[i]>=x) b[i]=1; //如果a[i]>=mid则变为1,否则变为-1
else b[i]=-1;
for(int i=1;i<=n;i++)
{
b[i]+=b[i-1]; //前缀和处理
minx[i]=min(b[i],minx[i-1]); //记录最小值
if(i>=k&&b[i]-minx[i-k]>=1) return true; //用b[i]-minx[i-k]>=1来判断是否存在合法的区间
}//这可以保证选取区间长度一定大于k,并且所用区间一定是以i为右端点的区间中大于等于mid的值最多的一个,省去了不必要的计算
return false;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int l=1,r=n; //二分答案
while(r>l)
{
int mid=l+r+1>>1;
if(check(mid)) l=mid; //如果符合要求,再看看有没有更大的解
else r=mid-1; //不符合要求则减小mid的值
}
printf("%d\n",l); //l即为最终答案
return 0;
}