#703 (Div. 2)D. Max Median(二分)

题目描述

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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值