#include #include using namespace std; // マージソートを行いながら転倒数(逆転の回数)をカウントする関数 long long merge_and_count(vector& A, int left, int right) { // 要素が1個以下の場合は逆転なし if (right - left <= 1) return 0; int mid = left + (right - left) / 2; // 左右に分割して再帰的に処理し、その逆転数を足し合わせる long long inv_count = 0; inv_count += merge_and_count(A, left, mid); inv_count += merge_and_count(A, mid, right); // マージ処理 vector temp; // 一時的な配列 int i = left; // 左側のインデックス int j = mid; // 右側のインデックス while (i < mid && j < right) { if (A[i] <= A[j]) { // 左側の方が小さい、または等しい場合は逆転ではない temp.push_back(A[i]); i++; } else { // 右側の方が小さい場合、左側の残りの要素すべてに対して逆転が発生する temp.push_back(A[j]); inv_count += (mid - i); j++; } } // 残りの要素を追加 while (i < mid) { temp.push_back(A[i]); i++; } while (j < right) { temp.push_back(A[j]); j++; } // 元の配列にソート結果を書き戻す for (int k = 0; k < (int)temp.size(); k++) { A[left + k] = temp[k]; } return inv_count; } int main() { // 入出力を高速化 ios_base::sync_with_stdio(false); cin.tie(NULL); int N; if (!(cin >> N)) return 0; vector A(N); for (int i = 0; i < N; i++) { cin >> A[i]; } // 0 から N までの半開区間 [0, N) で呼び出す long long ans = merge_and_count(A, 0, N); cout << ans << "\n"; return 0; }