[NC2018-9-9T1]中位数

题目大意:给你一个长度为$n$的序列,要求出长度大于等于$len$的字段的中位数中最大的一个中位数

题解:可以二分答案,对于比它小的数赋成$-1$,大的赋成$1$。求前缀和,若有一段区间的和大于$0$,说明这个数可以作为中位数。因为长度要大于等于$len$,所以可强制长度大于等于$len$。

如何求出最大字段和呢,可以求一个最小的前缀和,然后拿当前的前缀和减去就是以当前为结尾的最大字段和了

卡点:

 

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 100010
const int inf = 0x3f3f3f3f;
int n, len, ans;
int s[maxn], v[maxn];
int pre[maxn];
inline int getmin(int &a, int b) {if (b < a) a = b; return a;}
bool check (int x) {
	for (int i = 1, mn = inf; i <= n; i++) {
		pre[i] = pre[i - 1] + (s[i] >= x ? 1 : -1);
		if (i >= len && pre[i] - getmin(mn, pre[i - len]) > 0) return true;
	}
	return false;
}
int main() {
	scanf("%d%d", &n, &len);
	for (int i = 1; i <= n; i++) scanf("%d", s + i), v[i] = s[i];
	int l = 1, r = (std::sort(v + 1, v + n + 1), std::unique(v + 1, v + n + 1) - v - 1);
	while (l <= r) {
		int mid = l + r >> 1;
		if (check(v[mid])) {
			l = mid + 1;
			ans = mid;
		} else r = mid - 1;
	} 
	printf("%d\n", v[ans]);
	return 0;
}

  

posted @ 2018-09-09 14:38  Memory_of_winter  阅读(118)  评论(0编辑  收藏  举报