题意:给出你一个长度为n的序列,让你求长度最小为k的中位数的最大值。 1 < = a i < = n 1<=a_i<=n 1<=ai<=n
题解:首先我们通过数据范围可以看出,完全可以二分来做,左端是1,右端是n,其次我们看中位数,就是大于他的数比小于他的数一样多或者多一个。所以我们可以假设数组中只有两种元素,一种是比x小的我们定值为-1,另一种我们定值为1,这样,为了平衡-1与1,最终让他们处于一个平衡的状态,我们可以看出,如果存在一个范围值大于0,那么就说明中位数可以再大一点,如果没有那么我们就需要减小这个值,所以我们就找到了单调性。
这样我们维护一个前缀和,然后只需要判断是不是存在区间长度≥k的区间和为正数即可。
只需要维护一个前缀和的前缀最小值,然后枚举当前为区间终点,前缀最小值的位置为起点即可。
有必要说一下infac数组,它的用途是为了减去前缀小于0的那部分,就是从最小的后面开始。
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include <immintrin.h>
#pragma GCC optimize(2)
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<ll,ll> pii;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
const int maxn=2e5+1010;
#define inf 0x3f3f3f3f
#define sf scanf
#define pf printf
const int mod=998244353;
const int MOD=10007;
inline int read() {
int x=0;
bool t=false;
char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
/*
vector<ll> m1;
vector<ll> m2;
priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大
priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小
map<ll,ll>mp;*/
ll n;
ll a[maxn],k;
ll fac[maxn];
ll infac[maxn];
ll qpow(ll a,ll b) {
ll sum=1;
while(b) {
if(b&1) sum=sum*a%mod;
b>>=1;
a=a*a%mod;
}
return sum;
}
bool check(ll x){
for(int i=1;i<=n;i++){
if(a[i]>=x){
fac[i]=fac[i-1]+1;///判断这个数是大于他的多还是小于他的多
}else {
fac[i]=fac[i-1]-1;
}
infac[i]=min(infac[i-1],fac[i]);///最多可加的
}
for(int i=k;i<=n;i++){
if(fac[i]-infac[i-k]>0) return 1;
}
return 0;
}
#define read read()
int main() {
cin>>n>>k;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
ll l=1,r=n,ans=0;
while(l<=r){
ll mid=(l+r)/2;
if(check(mid)){
ans=mid;
l=mid+1;
}else {
r=mid-1;
}
}
cout<<ans<<endl;
return 0;
}