Gym 101170F Free Weights(二分)题解

题意:给出两行,每一行都有n个数组,一共有2 * n个,大小为1~n,每个有两个。现在可以进行操作:拿出一个物品i,然后放到一个空格,花费i。可以任意平移物品,平移没有花费。每一行空间无限。要求你把一样的数字要放在相邻位置,即1 1放一起,2 2放一起...问你你所有拿出的物品的最大花费max{ i }最小是多少。比如,我拿了1 2 3,那么最大花费max{ i }最小是3。

思路:我们二分这个答案m,显然比m小的可以直接移到末尾的无限空间,所以只要判断比m大的有没有成双成对就行。

打的时候居然没有想到!!!

代码:

#include<stack>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int n, w1[maxn], w2[maxn];
bool check(int m){
    stack<int> s;
    while(!s.empty()) s.pop();
    for(int i = 1; i <= n; i++){
        if(w1[i] > m){
            if(s.empty()) s.push(w1[i]);
            else if(!s.empty() && s.top() == w1[i]) s.pop();
            else return false;
        }
    }
    if(!s.empty()) return false;
    for(int i = 1; i <= n; i++){
        if(w2[i] > m){
            if(s.empty()) s.push(w2[i]);
            else if(!s.empty() && s.top() == w2[i]) s.pop();
            else return false;
        }
    }
    if(!s.empty()) return false;
    return true;
}
int main(){
    scanf("%d", &n);
    int Max = 0;
    for(int i = 1; i <= n; i++){
        scanf("%d", &w1[i]);
        Max = max(Max, w1[i]);
    }
    for(int i = 1; i <= n; i++){
        scanf("%d", &w2[i]);
        Max = max(Max, w2[i]);
    }
    int l = 0, r = Max;
    int ans = INF;
    while(l <= r){
        int m = (l + r) >> 1;
        if(check(m)){
            ans = m;
            r = m - 1;
        }
        else{
            l = m + 1;
        }
    }
    printf("%d\n", ans);
    return 0;
}

 

posted @ 2019-05-16 22:16  KirinSB  阅读(396)  评论(0编辑  收藏  举报