题目:
题目大意: 给定一个数列t,你构造两个数列a和b,使得max(a[i],b[i])=t[i]
核心思想: 1、先根据给出的数组进行放置,优先放到a数组中,如果这个数已经在a数组中出现了,再去放到b数组中
注意:a和b均为permutations ,也即1~n在a中必须出现,且只出现一次。
2、接下来先补全a数组:
把a数组中未出现的从大到小排序(用大根堆优先队列),记为t1
b数组中已经出现的从大到小排序(用sort排序)并记录下标,记为t2
因为这时两个都已经排好序了,最贪心的做法就是,把a最大的放到b最大的数所记录的下标位置 ,接着把a第二大的放到b第二大的数所记录的下标位置 ,接着把a第三大的放到b第三大的数所记录的下标位置……
这时一定是最优的,如果在放置的过程中,发现有个a中有个数比b的大,则之后的一定都比b的大,题目条件一定不满足
3、接下来先补全b数组(和上面类似):
把b数组中未出现的从大到小排序(用大根堆优先队列),记为t1
a数组中已经出现的从大到小排序(用sort排序),记为t2
如果能满足,则对于每一个t1[i],一定小于或等于t2[i]
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
#define ll long long
const int N = 2e5 + 10, M = 1e3 + 10;
int n, m, k, ans;
int a[N], b[N];
// a,b数组为最终的结果数组
bool st[N];
// st[i]为0时表示a数组i处已经放了,为1时表示b数组i处已经放了
bool v1[N], v2[N];
// v1[x]表示a数组中目前已经出现了x;v2[x]表示b数组中目前已经出现了x
struct E {
int u, id;
} t[N];
int cn;
bool cmp(E a, E b) {
return a.u > b.u;
}
int main() {
int T;
cin >> T;
int x;
priority_queue<int> q;
while (T--) {
cin >> n;
memset(v1, 0, sizeof(v1)); // 初始化
memset(v2, 0, sizeof(v2));
memset(st, 0, sizeof(st));
int f = 1; // 记录这次数组是否能满足
for (int i = 1; i <= n; i++) {
sf(x);
if (v1[x] == 0) {
v1[x] = 1;
a[i] = x;
st[i] = 0; // a数组i处已经放了
} else {
// 注意这里需要判断一下,如果某个数在a数组和b数组都已经放过了(即出现第三次)
// 则此时一定不满足
if (v2[x] == 1) {
f = 0;
}
v2[x] = 1;
b[i] = x;
st[i] = 1; // b数组i处已经放了
}
}
if (f == 0) {
printf("NO\n");
continue;
}
// 1、接下来补全a数组:
while (q.size())
q.pop();
cn = 0;
for (int i = 1; i <= n; i++) {
if (v1[i] == 0) {
q.push(i); // 找出a中没有出现的,放到优先队列中
}
if (st[i] == 1) {
t[++cn].id = i; // 找出b中已经出现的,放到结构体中
t[cn].u = b[i]; // 记录下标
}
}
sort(t + 1, t + cn + 1, cmp); // 结构体按照存储的数字从大到小排序
for (int i = 1; i <= cn; i++) {
if (q.top() > b[t[i].id]) {
f = 0;
break; // 如果此时b中已经出现过的小于a中未出现过的,则一定不满足
}
a[t[i].id] = q.top(); // 否则,把当前队列中最大的数补到a中
q.pop();
}
if (f == 0) {
printf("NO\n");
continue;
}
// 2、接下来补全b数组:
while (q.size())
q.pop();
cn = 0;
for (int i = 1; i <= n; i++) {
if (v2[i] == 0) {
q.push(i);
}
if (st[i] == 0) {
t[++cn].id = i;
t[cn].u = a[i];
}
}
sort(t + 1, t + cn + 1, cmp);
for (int i = 1; i <= cn; i++) {
if (q.top() > a[t[i].id]) {
f = 0;
break;
}
b[t[i].id] = q.top();
q.pop();
}
if (f == 0) {
printf("NO\n");
continue;
}
printf("YES\n");
for (int i = 1; i <= n; i++) {
printf("%d ", a[i]);
}
Pu;
for (int i = 1; i <= n; i++) {
printf("%d ", b[i]);
}
Pu;
}
}