贪心。我们先开一个答案序列。显然,一开始两个序列里有
0
0
0 就肯定先用上(但是要保证顺序,不能先用中间的再用前面的),从原先数组删除,插入答案序列,因为我们想要让行数越大越好,才能应对后面的数。如果都没有
0
0
0,那么就选更小的插入,因为这样才能保证成功的几率最大。如果最小的数都超过了现有的行数,那么这就说明不可能通过任何方法构造出合法的序列,我们就输出 -1
。最后,如果两个序列都空了并且没有输出 -1
,我们就输出答案序列。
我们可以设两个数 i i i 和 j j j,分别代表第一个序列和第二个序列分别已经删到哪里了。当 i i i 和 j j j 都走到数组的尽头时,就代表它们已经删空了。
AC 代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
int t;
cin >> t;
while(t--){
int k, n, m;
cin >> k >> n >> m;
int a[n + 1], b[m + 1];
for(int i = 0;i < n;i++){
cin >> a[i];
}
for(int i = 0;i < m;i++){
cin >> b[i];
}
a[n] = 0x3f3f3f3f, b[m] = 0x3f3f3f3f;
vector<int> ans; //答案序列
int l = k, ai = 0, bi = 0; //ai,bi分别表示两个数组分别删到了哪里,l为行数
bool flag = false;
while(ans.size() < n + m){
if(a[ai] == 0){
ai++, ans.push_back(0);
l++;
continue;
}
else if(b[bi] == 0){
bi++, ans.push_back(0);
l++;
continue;
}
int p = min(a[ai], b[bi]);
if(p == a[ai]){
ai++;
}
else{
bi++;
}
if(p > l){
flag = true;
break;
}
ans.push_back(p);
}
if(flag){
cout << -1 << endl;
}
else{
for(int i = 0;i < ans.size();i++){
cout << ans[i] << " "; //输出答案序列
}
cout << endl;
}
}
return 0;
}