【題目描述】
Prince對他在這片大陸上維護的秩序感到滿意,于是決定啟程離開艾澤拉斯。在他動身之前,Prince決定賦予King_Bette最強大的能量以守護世界、保衛這裡的平衡與和諧。在那個時代,平衡是個夢想。因為有很多奇異的物種擁有各種不穩定的能量,平衡瞬間即被打破。KB決定求助于你,幫助他完成這個夢想。
一串數列即表示一個世界的狀态。
平衡是指這串數列以升序排列。而從一串無序數列到有序數列需要通過交換數列中的元素來實作。KB的能量隻能交換相鄰兩個數字。他想知道他最少需要交換幾次就能使數列有序。
【輸入】
第一行為數列中數的個數n,第二行為n <= 10000個數。表示目前數列的狀态。
【輸出】
輸出一個整數,表示最少需要交換幾次能達到平衡狀态。
【輸入樣例】
4
2 1 4 3
【輸出樣例】
2
分析
- 此題求的需要交換兩個數順序的交換次數,也就是求逆序對的數量,因為一個逆序對說明兩個數的位置反了,一個逆序對就交換一次,是以可以用歸并排序來解這個題。
- 歸并排序也正是分治的思想,先不斷的将數組分成一塊一塊,然後在每兩塊合并的時候進行排序,最後合到一塊就是一個有序序列;
- 為什麼逆序對的數量是這個式子呢ans += mid - i + 1,因為當a[i]>a[j],此時 a[j] 與 左側數組剩餘的 mid-i+1 個數字構成逆序對 ;(說明a[j]不該放在 左側數組mid-i+1 個數字的後面,構成逆序對);
#include<bits/stdc++.h>
using namespace std;
int n, ans;
int a[10005], temp[10005];
void merge(int l, int mid, int r) {
int i = l;
int j = mid + 1;
int k = l;
while (i <= mid && j <= r) {
if (a[i] <= a[j]) {
temp[k++] = a[i++];
} else {
//逆序
ans += mid - i + 1;
temp[k++] = a[j++];
}
}
while (i <= mid) temp[k++] = a[i++];
while (j <= r) temp[k++] = a[j++];
for (int i = l; i <= r; i++) {
a[i] = temp[i];
}
}
void mergeSort(int l, int r) {
if (l >= r)
return;
int mid = l + (r - l) / 2;
mergeSort(l, mid);
mergeSort(mid + 1, r);
merge(l, mid, r);
}
int main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
mergeSort(1, n);
cout << ans;
}