Twist the Permutation-Codeforces
投稿日: 更新日:
問題
からの整数で構成された整数があります。です。
数列に対し以下の操作を行います。
番目の操作ではから番目までの要素を選び、右に任意の回数シフトする。
の配列を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;
}