每日一題1

yuzhongrun發表於2024-07-08

目錄
  • 每日一題Swap Dilemma
    • 真題連結
    • 思路:
    • 求逆序對
    • 我的程式碼

每日一題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;
}

相關文章