题意:
- A和B在打牌,B足够聪明,他能知道A的出牌顺序,现在决定B的出牌顺序,使得B出的牌能最多的比A出的牌大,如果有多个方案,则输出最大字典序
- 首先我们先求出最多能几张牌大于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