连续段的中数
最优解法
容易发现,答案是满足二分性质的。
二分答案,然后考虑怎么检查mid作为中数是否可行。
令所有大于等于mid的数字都为1,所有小于mid的数字都为-1,则相当于取一段长度大于等于k的数字使得数字和非负。用前缀和的思想,枚举右端点,然后维护
的前缀和最小值来得到以
为右端点长度大于等于k的连续段数字和最大值。当存在最大值非负的时候表明合法。
时间复杂度
因为只需要维护前缀最小和当前前缀和,所以可以省去前缀和数组的使用,空间复杂度
int solve(int n, int k, vector<int> &a){
assert(a.size() == n);
int l = 0, r = 1e9;
int ans;
while(l <= r){
int mid = (r+l)>>1;
int ps = 0, s = 0, cur = 0;
for(int i = 0; i < k; ++i)
if(a[i] >= mid) s ++;
else s--;
if(s >= 0){
ans = mid; l = mid+1; continue;
}
int flag = 0;
for(int i = k; i < n; ++i){
if(a[i-k] >= mid) cur++;
else cur--;
ps = min(ps, cur);
if(a[i] >= mid) s++;
else s--;
if(s-ps >= 0){
flag = 1; break;
}
}
if(flag) ans = mid, l = mid+1;
else r = mid-1;
}return ans;
}
查看22道真题和解析