Codeforces 1370 D

题意: 从长度为 n n 的序列 a a 中选 k k 个数组成序列 b b ,求出 m i n ( m a x ( b 2 k ) , m a x ( b 2 k + 1 ) ) min(max(b_{2k}), max(b_{2k+1}))
题解: 二分答案。我们不断缩小二分的答案 x x
由于是求奇数序列和偶数序列的最大值中的最小值,可以分别求这两者的最大值,若两个最大值都不符合条件,那么说明答案至少为 m i d + 1 mid+1 ,否则答案至多为 m i d mid
由于是求两者的最小值,最后二分的答案要么是正好奇数序列和偶数序列可以求得的最小值,即此时两者相同。或者只是其中一方的最小值。
可能的疑惑: 如果奇数序列或偶数序列中还可求出比当前答案还小的值,则会将左端点加 1 1 继续 c h e c k check ,直到答案是 m i n ( m a x ( b 2 k ) , m a x ( b 2 k + 1 ) ) min(max(b_{2k}), max(b_{2k+1}))
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5 + 10;
int n, k;
int q[N];

bool check(int x) {
	for(int i = 1, cnt = 0; i <= n; i++) { //even sequence
		//fetch q[i] when cnt is odd, so q[i] as b[2k] (k>=1) 
		if((cnt % 2 && q[i] <= x) || (cnt % 2 == 0)) cnt++;
		if(cnt >= k) return true;
	}
	for(int i = 1, cnt = 0; i <= n; i++) { // odd sequence
		//fetch q[i] when cnt is even, so q[i] as b[2k+1] (k>=0)
		if((cnt % 2 == 0 && q[i] <= x) || cnt % 2) cnt++;
		if(cnt >= k) return true;
	}
	return false;
}

int b_s(int l = 1, int r = 1000000000) {
	while(l < r) {
		int mid = l + r >> 1;
		if(check(mid)) r = mid;
		else l = mid + 1;
	}
	return l;
}

void solve() {
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= n; i++) scanf("%d", &q[i]);
	printf("%d\n", b_s());
}

int main()
{
	int T = 1;
	//scanf("%d", &T);
	while(T--) {
		solve();
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43900869/article/details/106913656