Codeforces Round #616 C Mind Control

题目大意

有 n 个人,排成一排,你站在 m 位置。恰巧有 n 个数,也排成一排。按照编号,每个人可以移除数列首位或者末尾的数,然后自己拿走这个被移除的数字。你可以说服最多 k 人,让他们选择数列首位或者末尾。然后你未说服的人,移除是随机的,不一定移除最大的数。

要求:你的选择是最优的,然后在所有情况下自己拿走的数都>=x,让你求出 x

思路

题目数据量不大,暴力就行了。

原谅我太菜,想了很久才想到暴力。

 首先可以肯定的是,k次操作必须要在自己操作之前进行才有效,而且,因为自己排在第m个,也就是说最多有m - 1个操作生效,轮到自己操作的时候,只剩下了n - m + 1个数字。

我们不妨让k < m,(大于的话后面的操作没用,相当于等于m - 1)

既然知道了k次操作要先进行,我们就可以直到k次操作后的开头数字的位置在哪。

未操作的时候一定是从1开始的,k此操作,如果都选择末尾的数字,开头还是在1,如果都选择开头数字,一定是从k + 1开始的,这是两个极端,那么可以肯定开头数字一定是1到k + 1其中一个数字,现在知道开头数字的位置了,有这么多种情况,可以一一列举计算。

k次操作后,还有m - 1 - k次操作才能轮到自己操作,但是这m - 1 - k次操作自己不能控制,可以知道的是,每次还是选择开头或者结尾,因此又可以知晓,如果k次操作完后开头在 i ,那么后面的m - 1 - k次操作后开头的范围在 i 到 i + m - 1 - k 之间。

又知道轮到自己操作时候的序列长度了,就可以根据开头位置计算末尾位置,对于自己可以控制的操作当然选最自己有利的(最大值),不受控制的就按照对自己不利的方向发展(最小值),最后在所有情况中选择答案最大的一种即可。

#include <bits/stdc++.h>
#pragma warning (disable:6031)
#pragma warning (disable:4996)
const int N = 3650;
int arr[N];
int ans[N];
int n, m, k;
const int inf = 1e9 + 10;
using namespace std;
int main()
{
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d %d %d", &n, &m, &k);
		for (int i = 1; i <= n; i++) {
			scanf("%d", arr + i);
		}
		k = min(k, m - 1);
		int res = -1;
		int tres;
		int len = n - m + 1;// 轮到自己操作时,剩下的数字个数(或序列长度)
		for (int i = 1; i <= k + 1; i++) {
			// k次操作受自己控制
			// 枚举k次操作后开头数字的下标
			// 轮到自己操作之前,一共有m - 1次操作
			// k次操作已进行
			// 剩下的m - 1 - k次就是自己控制不了的操作
			// 枚举这些操作过后的开头数字下标
			tres = inf;
			for (int j = i; j <= i + m - 1 - k; j++) {
				tres = min(tres, max(arr[j], arr[j + len - 1]));
			}
			res = max(res, tres);
		}
		printf("%d\n", res);
	}
	return 0;
}
发布了165 篇原创文章 · 获赞 11 · 访问量 9635

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104159428