给你两个长度为 n 的排列 a 和 b 。一个排列是由从 1 到 n 的 n 个元素组成的数组,其中所有元素都是不同的。例如,数组 [2,1,3] 是一个排列,但是 [0,1] 和 [1,3,1] 不是。
你可以(随心所欲地)选择两个索引 i 和 j ,然后同时把 ai 和 aj 以及 bi 和 bj 互换。
你讨厌倒置,所以你想尽量减少两次排列中倒置的总数。
排列组合 p 中的倒置是指一对索引 (i,j),即 i<j 和 pi>pj 。例如,如果有 p=[3,1,4,2,5] ,那么其中就有 3 个反转数(这对索引分别是 (1,2)、(1,4) 和 (3,4))。
输入
第一行包含一个整数 t (1 ≤ t ≤ 20000) - 测试用例的数量。
每个测试用例由三行组成。
第一行包含一个整数 n (1 ≤ n ≤ 2e5) - 排列 a 和 b 的长度。
第二行包含 n 个整数 a1,a2,…,an (1 ≤ ai ≤ n)--排列组合 a 和 b 的长度。
第三行包含格式类似的 b 。
保证所有测试用例中 n 的总和不超过 2e5。
输出
对于每个测试用例,输出两个排列 a′ 和 b′ (格式与输入相同)--所有操作后的排列。
a′ 和 b′ 中的反转总数应该是使用语句中的操作可以得到的所有排列对中的最小值。
如果有多个解,请打印其中任意一个。
Input
3
5
1 2 3 4 5
5 4 3 2 1
3
3 1 2
3 1 2
6
2 5 6 1 3 4
1 5 3 6 2 4
Output
3 2 5 1 4
3 4 1 5 2
1 2 3
1 2 3
2 3 4 6 5 1
1 2 4 3 5 6
注
在第一个测试案例中,可能的最小反转次数为 10 。
在第二个测试案例中,我们可以同时对两种排列进行排序。为此,可以进行以下操作:
交换两种排列中位于 1 和 3 位置的元素。操作后, a= [ 2,1,3 ] ,b= [ 2,1,3 ];交换位置 1 和 2 中的元素。
在第三个测试案例中,可能的最小反转数是 7 。
解析:
对于 a[i],a[j],b[i],b[j] ,其中i<j,一共4种情况。
1. a[i] > a[j] 且 b[i] > b[j],通过交换顺序可以将逆序对的个数减少 2 个;
2. a[i] > a[j] 且 b[i] < b[j],交换顺序,不改变逆序对的个数,一减一增;
3. a[i] < a[j] 且 b[i] > b[j],交换顺序,不改变逆序对的个数,一增一减;
4. a[i] < a[j] 且 b[i] < b[j],不需要交换。
可以看出,对于 2,3 和 4 的情况就不需要考虑。
对于 1 的情况,对一个序列进行升序排列即可,这样就能使得逆序对的个数最小。
#include <bits/stdc++.h>
#include <math.h>
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int gcd(int a,int b) { return b? gcd(b,a%b) : a; }
typedef pair<int,int> PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int n;
struct node
{int a,b;
}str[N];
bool cmp(node x,node y)
{return x.a<y.a;
}
void solve()
{cin>>n;for (int i=0;i<n;i++) cin>>str[i].a;for (int i=0;i<n;i++) cin>>str[i].b;sort (str,str+n,cmp);for (int i=0;i<n;i++) cout<<str[i].a<<" ";cout<<endl;for (int i=0;i<n;i++) cout<<str[i].b<<" ";cout<<endl;
}
signed main()
{ios;int T=1;cin>>T;while (T--) solve(); return 0;
}