公式
D - Inverse and Swap 解説
by
D - Inverse and Swap 解説
by
sheyasutaka
実装
順列 \(P\) を置換 \(\begin{pmatrix} 1 & 2 & \dots & N \\ P_1 & P_2 & \dots & P_N \end{pmatrix}\) と同一視するとき,種類 \(2\) のクエリは \(P\) をその逆置換 \(P^{-1} = \begin{pmatrix} P_1 & P_2 & \dots & P_N \\ 1 & 2 & \dots & N \end{pmatrix}\) に置き換える操作といえます.
現在の \(P,\ P^{-1}\) の値を管理することを考えます.このとき,各クエリは以下のように処理できます.
- 種類 \(1\) のクエリにおいて,\(P\) の要素に対する変更は \(P_x, P_y\) の swap のみであり,\(P^{-1}\) の要素に対する変更は \(P^{-1}_{P_x}, P^{-1}_{P_y}\) の swap のみ.
- \((P^{-1})^{-1} = P\) より,種類 \(2\) のクエリは単に \(P,\ P^{-1}\) を swap すればよい.これは愚直に swap しなくとも,\(2\) つの順列のどちらを \(P\) として扱うかを切り替える形で実装できる.
時間計算量は前処理 \(\Theta(N)\),クエリごとに \(\Theta(1)\),出力に \(\Theta(N)\) です.
実装例 (C++)
#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#include <vector>
using std::vector;
using std::pair;
#include <map>
using std::map;
#include <array>
using std::array;
using std::max;
using std::min;
using std::swap;
#ifdef DEBUG
const int debug = 1;
#else
const int debug = 0;
#endif
using ll = int64_t;
using P = pair<ll, ll>;
ll n, q;
vector<ll> a;
void solve () {
vector<ll> pq[2];
pq[0] = a;
pq[1].resize(n);
for (ll i = 0; i < n; i++) {
pq[1][a[i]] = i;
}
ll pi = 0;
for (ll qi = 0; qi < q; qi++) {
ll qt;
cin >> qt;
if (qt == 1) {
ll x, y;
cin >> x >> y;
--x;
--y;
// type 1 (swap)
ll px = pq[pi][x];
ll py = pq[pi][y];
swap(pq[pi ][x ], pq[pi ][y ]);
swap(pq[pi^1][px], pq[pi^1][py]);
} else {
// type 2 (inverse)
pi ^= 1;
}
}
for (ll i = 0; i < n; i++) {
if (i > 0) { cout << " "; }
cout << (pq[pi][i] + 1);
}
cout << "\n";
return;
}
int main (void) {
std::cin.tie(nullptr);
std::ios_base::sync_with_stdio(false);
cin >> n >> q;
a.resize(n);
for (ll i = 0; i < n; i++) {
cin >> a[i];
a[i]--;
}
solve();
return 0;
}
投稿日時:
最終更新:
