Official

E - Cheating Amidakuji Editorial by yuto1115

解説

\(B\) に対して \(k=1,2,\dots,i−1,i+1,\dots,M\) の順に問題文の操作を行うことで得られる数列」を \(C_i\ (1 \leq i \leq M)\) とおきます。また、「\(B\) に対して \(k=1,2,\dots,M\) の順に問題文の操作を行うことで得られる数列」を \(C_0\) とおきます。すべての \(C_i\) を愚直に求めるのは実行時間制限に間に合わないため、\(C_i\)\(C_0\) の操作列がほとんど同じ (\(k=i\) について操作をするかしないかの違いしかない) ことを利用して、高速に \(C_i\) を求められないか考えます。

実際、\(C_i\)\(C_0\) は、下記のように非常にシンプルな関係にあります。

  • \(B\) に対して \(k=1,2,\dots,i−1\) の順に問題文の操作を行うことで得られる数列」を \(C'\) とする (*)。また、\(x = C'_{A_i},y = C'_{A_i+1}\) とする。このとき、すべての \(j\ (1 \leq j \leq N)\) について以下が成り立つ。
    • \((C_0)_j \neq x\) かつ \((C_0)_j \neq y\) ならば、\((C_i)_j = (C_0)_j\)
    • \((C_0)_j = x\) ならば、\((C_i)_j = y\)
    • \((C_0)_j = y\) ならば、\((C_i)_j = x\)

例えば、\(C_0 = (1,3,x,2,y)\) のとき、\(C_i = (1,3,y,2,x)\) です。これらの関係は、「\(C_i\) においては、 \(k=i\) の操作を飛ばしたことでそれ以降での \(x\)\(y\) の位置が \(C_0\) の時と逆転するが、\(x\)\(y\) 以外には影響を及ぼさない」というように考えることで理解されます。

よって、\((C_0)_j = k\) を満たす \(j\) の値を \(pos_k\) とした時、\((C_i)_j = 1\) を満たす \(j\) の値は次のように求まります。

  • 前述 (*) と同じように \(C'\) を定義する。このとき、
    • \(C'_{A_i} \neq 1\) かつ \(C'_{A_i+1} \neq 1\) ならば、\(j = pos_1\)
    • \(C'_{A_i} = 1\) ならば、\(j = pos_{C'_{A_i+1}}\)
    • \(C'_{A_i+1} = 1\) ならば、\(j = pos_{C'_{A_i}}\)

\(i=1,2,\dots,M\) の順に \(C'\) を求め、上の規則を適用することによってこの問題を解くことができます。計算量は \(O(N+M)\) です。

実装例 (C++):

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> a(m);
    for (int &i: a) {
        cin >> i;
    }
    
    // k = 1,2,...,M について操作を行った場合に、1,2,...,N がそれぞれどこに行くかを求める
    vector<int> b(n + 1);
    iota(b.begin(), b.end(), 0);
    for (int i: a) {
        swap(b[i], b[i + 1]);
    }
    vector<int> pos(n + 1);
    for (int i = 1; i <= n; i++) {
        pos[b[i]] = i;
    }
    
    // 答えを求める
    iota(b.begin(), b.end(), 0);
    for (int i: a) {
        if (b[i] == 1) {
            cout << pos[b[i + 1]] << '\n';
        } else if (b[i + 1] == 1) {
            cout << pos[b[i]] << '\n';
        } else {
            cout << pos[1] << '\n';
        }
        swap(b[i], b[i + 1]);
    }
}

posted:
last update: