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

题意:

  • A和B在打牌,B足够聪明,他能知道A的出牌顺序,现在决定B的出牌顺序,使得B出的牌能最多的比A出的牌大,如果有多个方案,则输出最大字典序
【asia-yokohama-regional-contest-2018的K题题解】题解
  • 首先我们先求出最多能几张牌大于A的出牌,然后从A的第一张牌开始尽可能的用最大的牌,同时又不会破坏最多大于的,我们可以考虑如果当前选的牌是大于A[i]的,那么如果我把选的牌再变大,则满足最多的可能性会越来越小,所以是存在单调性的,这样我们就可以用二分来找出如果是要大于A[i]的最大牌而且又不会使得后面的最多大于被破坏,同时对于只能选小于或等于A[i]的牌,但我们选的牌越大,则满足最多的可能性就会越来越小,所以也是存在单调性的,所以这道题就分类二分就好了(对于满足一种性质,又要满足最大或最小,一般要用到二分)
#include 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 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 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

    推荐阅读