yukicoder No.365 - ジェンガソート

解法

後ろからブロックを見ていきます.
このとき一番後ろにあるべきブロックはNです. よってそれ以前にあるようなブロックは前に持っていかなければなりません. 次に後ろにあるべきブロックはN-1です. 一度場所が決定したブロックを再び動かして得をすることはないので, Nのブロックの次の位置から走査を開始します. ブロックを走査していく中で, N-1を見つけたらそれまでに見てきたブロックをすべて前に持っていきます. 同様のことを1まで繰り返していきます.
そしてブロックを動かす順番は好きに決定できるので結局動かすことになるブロックの数が問題になり, それを出力すればよいです.

ソースコード

#include <iostream>
#include <algorithm>
using namespace std;

const int kMAX_N = 100010;

int N;
int a[kMAX_N];

void Solve() {
    reverse(a, a + N);
    int ans = 0, s = 0, num = N;
    while (s < N) {
        int t = s;
        while (t < N && a[t] != num) {
            ans++;
            t++;
        }
        num--;
        s = t + 1;
    }
    cout << ans << endl;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> N;

    for (int i = 0; i < N; i++) {
        cin >> a[i];
    }

    Solve();

    return 0;
}

感想

最初Fenwick Treeを使う問題だとか思ってました()