#P15810. [JOI 2013 Final] バブルソート

[JOI 2013 Final] バブルソート

Description

バブルソートとは,列をソートするアルゴリズムの 1 つである.長さ NN の数列 AA を昇順にソートしたいとしよう.バブルソートは,隣り合う 2 つの数で大小関係が崩れているものがあれば,それらの位置を交換する.これを,数列を前から順に走査しながら行う.すなわち,Ai>Ai+1A_i > A_{i+1} となっている場所があれば,その 2 数を交換するということを,i=1,2,,N1i = 1, 2, \dots, N-1 に対してこの順で行うのが 1 回の走査である.この走査を N1N-1 回繰り返すことで,数列を昇順にソートできることが知られている.

数列 AA のバブルソートによる交換回数とは,数列 AA に上記のアルゴリズムを適用した時に,整数の交換が行われる回数である.(バブルソートとして知られるアルゴリズム及び実装には,ループの順番や範囲,及び終了条件など,細かな差異がある場合がある.ただし,同じ数列に適用した際の整数の交換回数はそれらの差異により変化しないことが知られている.)

例えば,以下のプログラムは長さ nn の整数の配列 aa をバブルソートによりソートする関数を C 言語で記述したものである.

void bubble_sort(int *a, int n) {
    int i, j;
    for (i = 0; i < n - 1; ++i) {
        for (j = 0; j < n - 1; ++j) {
            if (a[j] > a[j + 1]) {
                /* 以下 3 行が 1 回の整数の交換に相当 */
                int x = a[j];
                a[j] = a[j + 1];
                a[j + 1] = x;
            }
        }
    }
}

課題

長さ NN の数列 AA が与えられる.数列 AA の任意の場所の 2 つの整数を 1 回だけ交換した数列 AA' を作るとする.数列 AA' のバブルソートによる交換回数の最小値を求めるプログラムを作成せよ.(最初に交換する 2 つの整数は必ずしも隣り合っている必要はないことに注意せよ.)

Input Format

標準入力から以下のデータを読み込め.

  • 1 行目には,整数 NN が書かれている.NN は数列 AA の長さを表す.
  • 続く NN 行のうちの ii 行目 (1iN1 \leq i \leq N) には,整数 AiA_i が書かれている.これは数列 AAii 番目の整数を表す.

Output Format

標準出力に,数列 AA' のバブルソートによる交換回数の最小値を表す整数を 1 行で出力せよ.

5
10
3
6
8
1
0
5
3
1
7
9
5
2
3
1
2
3
1

Hint

入出力例 1

数列 AA の最初の 1010 と最後の 11 を交換することにすると,数列 AA' はソート済みの列となり,バブルソートの交換回数は 00 となる.

入出力例 2

数列 AA の 3 番目の 77 と最後の 55 を交換することで,数列 AA'3,1,5,9,73,1,5,9,7 となる.AA' のバブルソートによる交換回数は 22 である.

入出力例 3

最初から数列 AA がソートされている場合でも,数列 AA' を作る際に交換を行わなければならない.

制限

1N1000001 \leq N \leq 100\,000 数列 AA の長さ
1Ai10000000001 \leq A_i \leq 1\,000\,000\,000 数列 AA に含まれる数字の大きさ

採点基準

採点用データのうち,配点の 10% 分については,N1000N \leq 1000 を満たし,任意の i,ji, j (1i<jN1 \leq i < j \leq N) について AiAjA_i \neq A_j を満たす.
採点用データのうち,配点の 30% 分については,N5000N \leq 5000 を満たし,任意の i,ji, j (1i<jN1 \leq i < j \leq N) について AiAjA_i \neq A_j を満たす.
採点用データのうち,配点の 80% 分については,任意の i,ji, j (1i<jN1 \leq i < j \leq N) について AiAjA_i \neq A_j を満たす.