div2D:Swap Dilemma
每日一题Swap Dilemma
真题链接
思路:
我们显然知道两个数组元素集合不一样时一定返回NO
例如
输入1:
3
1 4 2
1 3 2
输出1:
NO
可以排序后一一比对即可
现在需要解决的就是一个数组的两个序列能不能通过等距交换最终相同
例如:
输入2:
5
1 5 7 1000 4
4 1 7 5 1000
输出2:
NO
输入3:
4
1 2 3 4
4 3 2 1
输出3:
YES
那么该如何判断是否可以变换后相等呢?
在第三个测试用例中,使数组相同的方法之一(不唯一)是
首先选择 l=1 、 r=3 、 p=1、 q=3,变成 3 2 1 4 和 2 3 4 1
然后选择 l=1 、 r=2 、 p=3 、q=4 。变成2 3 1 4 和 2 3 1 4
这个时候就相等了交换结束。
...but这个时候我们继续交换,每次选择相邻两个数两个数组交换(冒泡排序)最终结果两个数组都是 1 2 3 4
欸!🤓👌。我们知道容易一个数组都可以两两交换变成有序的,那不是就是所有情况都可以交换到最终有序输出YES了,不不不,我们看一个样例 1 2 3 , 1 3 2 我们发现怎么交换另外一个数组也必须同时交换这样就不能两个数组同时有序.这就需要两个数组变成有序的步骤差是偶数(很容易想明白).这个冒泡排序的交换次数就是逆序对,也就是说两个数组的逆序对差值为偶数.
求逆序对
可以借用归并排序或者树状数组
归并排序模板以及求解逆序对模板_归并排序求逆序对板子-CSDN博客
P1908 逆序对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
我的代码
#include <bits/stdc++.h>
#include<functional>
#define debug cout<<"debug"<<endl;
#define debug1(a) cout << #a << '=' << a << endl;
#define debug2(a, b) cout << #a << " = " << a << " " << #b << " = " << b << endl;
#define debug3(a, b, c) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << endl;
#define debug4(a, b, c, d) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << " " << #d << " = " << d << endl;
#define debug5(a, b, c, d, e) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << " " << #d << " = " << d << " " << #e << " = " << e << endl;
#define caseT \
int T; \
cin >> T; \
while (T--)
//#define M(x, y) make_pair(x, y)
//#define M(x, y, z) make_tuple(x, y, z)
//#define int long long
//#define int __int128
using namespace std;
//using str = string;
using ull = unsigned long long;
using ll = long long;
//using pii = pair<int, int>;
//using tiii = tuple<int, int, int>;
const int N = 2e5+10;
const int M = (int)1e6;
const ll mod = LLONG_MAX;
int n;
ll a[M + 5],a2[M+5];
ll b[M + 5];
ll merge_sort(ll a[], int l, int r)
{
if(l >= r) return 0;
int mid = (l + r) >> 1; ll cnt = (merge_sort(a, l, mid) + merge_sort(a, mid + 1, r)) % mod;
int i = l, j = mid + 1, k = 0;
while(i <= mid && j <= r) if(a[i] <= a[j]) b[++k] = a[i++]; else b[++k] = a[j++], (cnt += mid - i + 1) %= mod;
while(i <= mid) b[++k] = a[i++];
while(j <= r) b[++k] = a[j++];
for(int i = l, j = 1; i <= r; ++i, ++j) a[i] = b[j];
return cnt;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
ll ma=merge_sort(a, 1, n);
//cout<<"ma="<<ma<<endl;
for(int i=1;i<=n;i++)cin>>a2[i];
ll mb=merge_sort(a2, 1, n);
//cout<<"mb="<<mb<<endl;
for(int i=1;i<=n;i++){
if(a[i]!=a2[i]){
cout<<"NO"<<endl;return;
}
}
if(abs(ma-mb)%2==0)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
caseT
solve();
return 0;
}