asia-yokohama-regional-contest-2018的K题题解

题意:

  • A和B在打牌,B足够聪明,他能知道A的出牌顺序,现在决定B的出牌顺序,使得B出的牌能最多的比A出的牌大,如果有多个方案,则输出最大字典序

题解

  • 首先我们先求出最多能几张牌大于A的出牌,然后从A的第一张牌开始尽可能的用最大的牌,同时又不会破坏最多大于的,我们可以考虑如果当前选的牌是大于A[i]的,那么如果我把选的牌再变大,则满足最多的可能性会越来越小,所以是存在单调性的,这样我们就可以用二分来找出如果是要大于A[i]的最大牌而且又不会使得后面的最多大于被破坏,同时对于只能选小于或等于A[i]的牌,但我们选的牌越大,则满足最多的可能性就会越来越小,所以也是存在单调性的,所以这道题就分类二分就好了(对于满足一种性质,又要满足最大或最小,一般要用到二分)
#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5+9;

int a[maxn],b[maxn],tmp[maxn];
int res;
int n;

bool check(int id, int x, vector<int> G){
    int ans = (tmp[id] < G[x]);
    int l = n , r = G.size()-1;
    while(l > id && r>=0){
        if(r == x)r--;
        if(tmp[l] < G[r]){
            ans++; l--; r--;
        }
        else l--;
    }
    return ans == res;
}

int main(){
    while(~scanf("%d",&n)){
        vector<int> G;
        for(int i = 1; i <= n; i++)scanf("%d",&a[i]),tmp[i]=a[i];
        for(int i = 1; i <= n; i++)scanf("%d",&b[i]),G.push_back(b[i]);
        sort(b+1,b+1+n);
        sort(tmp+1,tmp+1+n);
        int l,r;
        l = r = n;
        res = 0;
        while(l&&r){
            if(tmp[l] < b[r]){
                --r; --l; res++;
            }
            else --l;
        }
        sort(G.begin(),G.end());
        for(int i = 1; i <= n; i++){
            copy(a+1,a+1+n,tmp+1);
            sort(tmp+i+1,tmp+1+n);
            int l = upper_bound(G.begin(),G.end(),a[i])-G.begin();
            int r = G.size()-1;
            while(l < r){
                int mid = l+(r-l+1)/2;
                if(check(i,mid,G)) l = mid;
                else r = mid-1;
            }
            if(check(i,r,G)){
                if(a[i] < G[r])res--;
                printf("%d",G[r]);
                G.erase(G.begin()+r);
            }
            else{
                int l = 0,r = upper_bound(G.begin(),G.end(),a[i])-G.begin()-1;
                while(l<r){
                    int mid = l+(r-l+1)/2;
                    if(check(i,mid,G))l=mid;
                    else r=mid-1;
                }
                if(a[i] < G[r])res--;
                printf("%d",G[r]);
                G.erase(G.begin()+r);
            }
            if(i<n)printf(" ");
            else printf("\n");
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章