CodeForces - 1290A - Mind Control(思维)

题目链接:https://vjudge.net/problem/CodeForces-1290A#author=zzuli_practice

题目大意:每个人都能做一个操作,拿走数列中的第一个数或者第二个数,你可以指定k个人拿走的数,你是第m

个人,问你能拿到的最小的数最大是多少?

这题的思路有点像尺取(类似于游标卡尺的操作吧,不过这回游标的固定长度的).首先可以明确的是,轮到第m次选的时候

你可以选这个数列的第一个数,也可以选最后一个,因为m-1是固定的,所以剩下的数列个数也是固定的,我们把这个剩下的

数列称为"游标", 那么他的移动范围呢?如果我们指定k个人都取最后面的,那么他的最左端就是第一个数, 如果我们指定k个人

都取最前面的,那么他的最左端就是k+1个数, 所以他的移动范围就是1-k+1, 那么我们假设前k个数选好了,要求剩下的人随机选的情况

下选出的最小的数的最大值怎么办呢?其实我们可以再弄一个"游标", 因为前面已经选过k个数了,那么剩下随机选的个数(不算自己)就是m-k-1个

以第一个游标的位置为0位置,那么第二游标的最左端的范围就是0~m-k-1,然后在最优策略下,选出的数就是第二游标左右端点的最大值,最后我们只要求

这些最大值之中的最小值就行了

#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '\n'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define maxx(a, b) (a > b ? a : b)
#define minn(a, b) (a < b ? a : b)
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  1000000007LL;
const int INF = 0x3f3f3f3f;
const int _NAN = -0x3f3f3f3f;
const double EULC = 0.5772156649015328;
const int NIL = -1;
template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
const int maxn = 1e4+10;
int arr[maxn];
int main(void) {
    int t;
    scanf("%d", &t);
    while(t--) {
        zero(arr);
        int m, n, k;
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 0; i<n; ++i)
            scanf("%d", &arr[i]);
        int ans = -1;
        if (k>=m) k = m-1; //最理想情况下我们只要m前面的数都可以指定就可以
        for (int i = 0; i<=k; ++i) {
            int temp = INF;
            for (int z = 0; z<=m-k-1; ++z)
                temp = min(temp, max(arr[z+i], arr[z+i+n-m])); //第二游标的区间长度就是选掉m个数之后的长度+1即n-m+1
            ans = max(ans, temp);                              //因为下标从0开始了就是n-m了
        }
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shuitiangong/p/12426098.html