[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; }