Twist the Permutation-Codeforces

投稿日: 更新日:

問題リンク-Twist the Permutation

問題

11からnnの整数で構成された整数があります。ai=ia_i = iです。

数列に対し以下の操作を行います。

ii番目の操作では11からii番目までの要素を選び、右に任意の回数シフトする。
a=[a1,a2,...,an]a = [a_1, a_2, ..., a_n]の配列を1回シフトすると
a=[ai,a1,...,ai1,ai+2,...,an]a = [a_i, a_1, ..., a_{i-1}, a_{i+2}, ..., a_n]となる

操作後の配列が与えられます。それぞれの操作で何回シフトするのかをスペース区切りで出力してください。答えが存在しなければ1-1を出力してください。

解法

後ろから見ていきます。

一番後ろの要素ana_nに注目します。
ana_nが動くのはnn番目の操作のみです。したがって、与えられた数列の位置との差から操作の回数が決まります。nn番目の操作回数が決まれば、次はn1n-1の操作回数が決まります。再帰的に繰り返すことにより答えが求まります。

実装

#include <bits/stdc++.h>
using namespace std;

void solve(){
    int n;
    cin >> n;
    vector<int> a(n);
    map<int,int> mp;
    for(int i = 0;i < n; ++i){
        cin >> a[i];
        a[i]--;
        mp[a[i]] = i;
    }

    vector<int> ans;
    for(int i = n-1; i >= 0; --i){
        int index = mp[i];
        int ope = index - i;
        if(ope < 0){
            ope = (i+1) + ope;
        }

        ans.push_back(ope);

        vector<int> shift = a;
        for(int j = 0;j <= i; ++j){
            int p = (j - ope + i+1) %(i+1);
            shift[p] = a[j];
            mp[a[j]] = p;
        }


        swap(shift, a);
    }

    cout << ans[n-1];
    for(int i = n-2;i >= 0; --i){
        cout << " " << ans[i];
    }
    cout << endl;
}

int main(){
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

書いた人

profile_image

お茶の葉

物理とプログラミングが好きな人