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;
}

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