Official

F - Simultaneous Swap Editorial by en_translator


Takahashi’s operation is an operation of permutation, so if \(A\) and \(B\) do not coincide as multisets, repeating the operation do never make them equal. Now we assume that the elements are equal as multisets.

1. If the elements of \(A\) are distinct

How does the sum of inversion numbers of \(A\) and \(B\) change by the operation? Here, the inversion number of \(A\) is the number of integer pairs \((i,j)\) such that \(1\leq i<j\leq N\) and \(A_i>A_j\). The parity of the inversion number always flips by a transposition (exchanging two elements). Takahashi’s operation always applies transposition to \(A\) and \(B\) once, so the parity of the sum of the inversion numbers of \(A\) and \(B\) is invariant by his operation. When \(A\) coincides \(B\), so do their inversion numbers, whose sum is even. Thus, if their sum is odd in the initial state, it is impossible to make them equal.
Conversely, if they coincide, you can always make them equal. First of all, by performing the following operation for each \(x=1,2,\ldots,N-2\), the operation up to \(x=x_0\) makes \(A_i=B_i\) for all \(1\leq i\leq x_0\).

  1. If \(A_x=B_x\), do nothing.
  2. Otherwise, we can take \(x+1\leq y\leq N\) such that \(A_x=B_y\) since \((A_x,A_{x+1},\ldots,A_N))\) is a permutation of \((B_x,B_{x+1},\ldots,B_N))\).
  3. Moreover, we can take \(x+1\leq z\leq N\) such that \(z\neq y\).
  4. Do the operation with \((i,j,k)=(y,z,x)\). While \(A_i\) and \(B_i\) remain invariant within \(1\leq i\leq x-1\), now \(A_x=B_x\) by the operation.

After this sequence of operations, \(A\) and \(B\) can be in one of the two states: \(A\) coincides with \(B\), or \(A\) and \(B\) differ in the last two elements where the \((N-1)\)-th and \(N\)-th elements are swapped. However, the former has a even sum of inversion numbers, while the latter has odd; thus, if it is even, they always coincide. Therefore, if the inversion number coincides, we can always make them equal.

2. If \(A\) contain the same element twice or more

With an arbitrary tie break, one can take a permutation \(A'\) of \((1,2,\ldots,N)\) such that \(A'_i<A'_j\) for all \(1\leq i,j\leq N\). We similarly take \(B'\) for \(B\). Additionally, there exists \(1\leq i<j\leq N\) such that \(A_i=A_j\). Let \(\tilde{A}'=(\tilde{A}'_1,\ldots,\tilde{A}'_i,\ldots,\tilde{A}'_j,\ldots,\tilde{A}'_N)=(A'_1,\ldots,A'_j,\ldots,A'_i,\ldots,A'_N)\) be the one obtained by swapping \(A'_i\) and \(A'_j\) of \(A'\). Note that it remains that \(\tilde{A}'_i<\tilde{A}'_j\) if \(A_i\leq A_j\) for all \(1\leq i,j\leq N\).

Here, since \(\tilde{A}'\) was obtained by applying a transposition on \(A'\) exactly once, the parties of the inversion numbers are different. Thus, exactly one of the following two are even: the sum of the inversion numbers of \(A'\) and \(B'\), and that of \(\tilde{A}'\) and \(B'\). So one can repeat the operation to make \(A'\) equal \(B'\), or \(\tilde{A}'\) equal \(B'\). Applying the same sequence of operations against \(A\) and \(B\), \(A_i\) results in the \(A'_i\)-th (or \(\tilde{A}'_i\)-th) element of \(A\) when sorted in ascending order, so if \(A'_i=B'_i\) (or \(\tilde{A}'_i=B'_i\)), then \(A_i=B_i\). Therefore, (as long as they are equal as multisets) we can always make them equal.

Thus, it is sufficient to determine if \(A\) and \(B\) coincide as multisets, and find their inversion numbers. These can be performed in \(O(N\log N)\) time, so the problem has been solved fast enough.

By the way, since \(1\leq A_i,B_i\leq N\), this problem can also be solved in a total of \(O(N)\) time.

Sample code (C++):

#include <bits/stdc++.h>
#include <atcoder/all>

using namespace std;
using namespace atcoder;

#define rep(i, n) for(int i = 0; i < n; ++i)

int main(void) {
	int n;
	cin>>n;
	vector<int>a(n),b(n);
	fenwick_tree<long long> c(n),d(n);
	long long z=0;
	rep(i,n){
		cin>>a[i];
		z+=c.sum(a[i],n);
		c.add(a[i]-1,1);
	}
	rep(i,n){
		cin>>b[i];
		z+=d.sum(b[i],n);
		d.add(b[i]-1,1);
	}
	sort(a.begin(),a.end());
	sort(b.begin(),b.end());
	rep(i,n)if(a[i]!=b[i]){
		cout<<"No"<<endl;
		return 0;
		}
	rep(i,n-1)if(a[i]==a[i+1]){
		cout<<"Yes"<<endl;
		return 0;
		}
	if(z%2)cout<<"No"<<endl;
	else cout<<"Yes"<<endl;
	return 0;
}

posted:
last update: