Official

F - Simultaneous Swap Editorial by mechanicalpenciI


高橋君が行うことができる操作は並べ替えの一種であるため、\(A\)\(B\) の要素を多重集合として見たときに一致してない場合は操作の繰り返しによって一致させることはできません。 以下、多重集合として見たときに一致している場合について考えます。

1. \(A\) の要素がすべて異なる場合 (すなわち、\((1,2,\ldots,N)\) の順列となっている場合)

\(A,B\) の反転数の和の偶奇が操作でどう変化するかについて考えます。ここで、\(A\) の反転数とは、\(1\leq i<j\leq N\) かつ \(A_i>A_j\) をみたす整数の組 \((i,j)\) の個数の事です。反転数の偶奇は互換操作(特定の \(2\) つの要素を選んで入れ替える操作) によって必ず反転します。高橋君の行う操作では、\(1\) 回の操作で \(A,B\) に対してちょうど一度ずつ互換操作を行なっているため、\(A,B\) の反転数の総和の偶奇は高橋君の操作によって変化しません。\(A,B\) が一致している時、反転数も等しいですから、その和は偶数となります。よって、最初の時点で反転数の総和が奇数である場合は一致させる事ができません。
逆に、そうで無い場合は必ず一致させる事ができます。 まず、次の操作を \(x=1,2,\ldots,N-2\) に対して順に行う事で、\(x=x_0\) についての操作までで、 \(1\leq i\leq x_0\) に対して \(A_i=B_i\) となるようにする事ができます。

  1. \(A_x=B_x\) ならば何もしない
  2. そうでない時、\((A_x,A_{x+1},\ldots,A_N))\)\((B_x,B_{x+1},\ldots,B_N))\) の並び替えであるから、\(x+1\leq y\leq N\) であって、\(A_x=B_y\) であるようなものが取れる。
  3. さらに、\(x+1\leq z\leq N\) であって、\(z\neq y\) であるようなものが取れる。
  4. \((i,j,k)=(y,z,x)\) として操作を行う。この操作で、\(1\leq i\leq x-1\) の範囲の \(A_i,B_i\) が変化する事はなく、操作の後で新しく \(A_x=B_x\) となる。

この操作の後で、\(A,B\) の関係としては、\(A\)\(B\) が一致している場合と、\(B\)\(A\)\(N-1\) 番目の要素と \(N\) 番目の要素を互換したものになっている場合の \(2\) 通りが考えられます。しかし、前者では反転数の和は偶数、後者では奇数となっていることから、反転数の和が偶数である場合は必ず一致している事がわかります。 よって、反転数の和が偶数ならば必ず一致させられることが分かりました。

2. \(A\) の中に \(2\) 回以上登場する要素が存在する場合

\(A\) に対して、同一の要素に対しても適当に大小関係をつけることで、\((1,2,\ldots,N)\) の順列 \(A'\) であって、\(1\leq i,j\leq N\) に対して \(A'_i<A'_j\) ならば \(A_i\leq A_j\) となるようなものをとることができます。\(B\) に対しても同様にして \(B'\) をとります。 さらに、\(1\leq i<j\leq N\)であって \(A_i=A_j\) であるようなものが存在します。そのような \((i,j)\)\(1\) つとり、\(A'\) から \(A'_i\)\(A'_j\) を入れ替えたものを \(\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)\) とします。この場合についても任意の \(1\leq i,j\leq N\) に対して \(\tilde{A}'_i<\tilde{A}'_j\) ならば \(A_i\leq A_j\) が成り立っている事に注意します。

さて、\(\tilde{A}'\)\(A'\) に対してちょうど \(1\) 回互換を行なったものであるから、反転数の偶奇は異なり、\(A'\) の反転数と \(B'\) の反転数の和と、\(\tilde{A}'\) の反転数と \(B'\) の反転数の和のうちどちらかちょうど一方が偶数となり、操作を繰り返す事で、\(A'\)\(B'\) または \(\tilde{A}'\)\(B'\) を一致させることができます。 同様の操作を \(A,B\) に行うと、\(A_i\)\(A\) を昇順にソートした時に \(A'_i\) ( または \(\tilde{A}'_i\) ) 番目に来る要素となる (\(B\) についても同様) ため、\(A'_i=B'_i\) ( または \(\tilde{A}'_i=B'_i\) ) ならば \(A_i=B_i\) となります。 よって、この場合は (多重集合として一致していれば) つねに一致させることができます。

以上より、\(A,B\) が多重集合として一致しているかと それぞれの反転数を求めればよく、これらは \(O(N\log N)\) で確認することができるため、十分高速にこの問題を解くことができました。

なお、\(1\leq A_i,B_i\leq N\) である事を利用して工夫する事によって、この問題は \(O(N)\) で解く事もできます。

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: