CodeForces 1290A Mind Control(思维)
题目大意
有一个长度为\(n\)的序列,每个人都能拿走序列中的第一个数或者最后一个数,你可以指定\(k\)个人拿的顺序,问第\(m\)个人拿的数最大是多少。
分析
既然这个题的数据不大那么就尽可能的往暴力的方面想,有没有办法列举出所有的情况呢?先看一下下图:
可以很容易的看出,对于选定\(k\)个之后可选的区间会是一个长度为\(n-k\)的滑块,我们要做的就是枚举出滑块里面所有的情况,再让滑块移动,改变区间,再进行枚举,那么滑块里面是什么情况呢?
在黑滑块里面还有一个红色子滑块,这个子滑块的头尾两个数之间的最大值就是每种情况要选的数(因为要最优所以选最大的)。而这个滑块可以移动的范围就是选完\(k\)个之后到\(m\)之间的那几个数,因为这几个选择是不能指定的,所以对于一个固定的黑滑块来说,其最优的情况就是所有最优解的最小值。而对于整个序列来说,因为前\(k\)个人是可以指定的,所以最优解就是所有最优解最小值中的最大值。
具体实现
实现上没什么好说的,主要是计算方面可能有点问题。首先需要注意的是如果\(k\)大于\(m-1\)的话取\(m-1\)就行了,再大了也不会对结果又影响而且实现起来还会带来麻烦。然后就是注意一下计算各个滑块长度与可移动距离的大小就行了。
代码
const int maxn = 1e4+10;
int arr[maxn];
int main(void) {
int t;
cin >> t;
while(t--) {
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i<=n; ++i) cin >> arr[i];
if (k>=m) k = m-1;
int ans = -1, len1 = n-k, len2 = len1-(m-k-1);
for (int i = 1; i<=k+1; ++i) {
int tmp = INF;
for (int j = i; j<=i+m-k-1; ++j)
tmp = min(tmp, max(arr[j], arr[j+len2-1]));
ans = max(ans, tmp);
}
cout << ans << endl;
}
return 0;
}