Codeforces-1486 D. Max Median(中位数,二分)

在这里插入图片描述
题意:
求子区间大小不小于 k k k能得到的最大中位数。这里的中位数定义为排序后第 ( n + 1 ) 2 \frac{(n+1)}{2} 2(n+1)的数。

思路:
二分这个这个最大的中位数 m i d mid mid,将数组中大于 m i d mid mid的位置设置为1,否则设置为-1。这样问题就变成了能否找到大于 k k k的和大于0的区间,这个用前缀和维护一下就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <queue>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int a[maxn],b[maxn],c[maxn];
int n,k;
bool check(int mid) {for(int i = 1;i <= n;i++) {if(a[i] >= c[mid]) {b[i] = 1;} else {b[i] = -1;}}int sum = 0,pre = 0,mi = 0;int flag = 0;for(int i = 1;i <= k - 1;i++) sum += b[i];for(int i = k;i <= n;i++) {sum += b[i];if(sum - mi > 0) {flag = 1;break;}pre += b[i - k + 1];mi = min(mi,pre);}return flag;
}
int main() {scanf("%d%d",&n,&k);for(int i = 1;i <= n;i++) {scanf("%d",&a[i]);c[i] = a[i];}sort(c + 1,c + 1 + n);int l = 1,r = n;int ans = l;while(l <= r) {int mid = (l + r) >> 1;if(check(mid)) {ans = mid;l = mid + 1;} else {r = mid - 1;}}printf("%d\n",c[ans]);return 0;
}