給定長度為 n 的排列(元素為 0 到 n-1),視為環狀序列。共有 n 個長度為 n 的線性序列(每個元素作為起點一次)。求這 n 個序列中的最小逆序數。
設原序列逆序數為 inv。將首元素 a 移至序列末尾,逆序數變化為:
Δ = (比 a 大的元素個數) - (比 a 小的元素個數) = (n - 1 - a) - a = n - 1 - 2a
因此可 O(n) 依次計算所有輪轉序列的逆序數並取最小值。
const int MAXN = 5005;
int C[MAXN], a[MAXN];
int lowbit(int x) { return x & -x; }
int query(int x) {
int res = 0;
while (x > 0) { res += C[x]; x -= lowbit(x); }
return res;
}
void update(int x, int d) {
while (x <= n) { C[x] += d; x += lowbit(x); }
}
// 計算初始逆序數
int inv = 0;
for (int i = 1; i <= n; ++i) {
update(a[i] + 1, 1); // 值域 0..n-1,映射到 1..n
inv += i - query(a[i] + 1);
}
long long 存儲