給定 1~n 的一個排列,每次只能交換相鄰元素,求排序為升序所需最少交換次數。即求排列的逆序對數。n ≤ 1000, T ≤ 1000。
從左到右遍歷排列。對於當前元素 `a[i]`,已處理元素中大於它的個數即為以它為右端點的逆序對數。用樹狀數組維護值域頻率前綴和。
#include
#include
const int MAXN = 1005;
int bit[MAXN];
int lowbit(int x) { return x & -x; }
void add(int idx, int val) {
for (; idx < MAXN; idx += lowbit(idx)) bit[idx] += val;
}
int sum(int idx) {
int res = 0;
for (; idx > 0; idx -= lowbit(idx)) res += bit[idx];
return res;
}
int main() {
int T; scanf("%d", &T);
while (T--) {
int n; scanf("%d", &n);
memset(bit, 0, sizeof(bit));
long long ans = 0;
for (int i = 1; i <= n; i++) {
int x; scanf("%d", &x);
// 已有 i-1 個數,其中 ≤x 的有 sum(x) 個,>x 的有 (i-1) - sum(x) 個
ans += (i - 1) - sum(x);
add(x, 1);
}
printf("%lld\n", ans);
}
return 0;
}
歸併排序求逆序對同樣 O(n log n),代碼稍長但無值域限制。本題值域小,BIT 更簡潔。