10 1 3 6 9 0 8 5 7 4 2
16
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 using namespace std; const int maxn = 5555; int sum[maxn << 2]; int a[5555]; void PushUp(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void build(int l, int r, int rt) { if (l == r) { sum[rt] = 0; return; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } int query(int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return sum[rt]; } int m = (l + r) >> 1; if (R <= m) return query(L, R, lson); else if (L > m) return query(L, R, rson); else if (L <= m && R > m) return query(L, m, lson) + query(m + 1, R, rson); } //等价query另类写法 /* int query(int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return sum[rt]; } int m = (l + r) >> 1; int res = 0; if (L <= m) res += query(L, R, lson); if (R > m) res += query(L, R, rson); return res; } */ void update(int p, int l, int r, int rt) { if (l == r) { sum[rt]++; return; } int m = (l + r) >> 1; if (p <= m) update(p, lson); else update(p, rson); PushUp(rt); } int main() { int N; while (~scanf("%d", &N)) { build(0, N - 1, 1); int ans = 0; for (int i = 0; i < N; i++) { scanf("%d", &a[i]); //查询>a[i]的之前输过的数有几个,就是这个数的逆序数 ans += query(a[i], N - 1, 0, N - 1, 1); //将这个数记录下来,供后面的数计算逆序数 update(a[i], 0, N - 1, 1); } int minn = ans; /*将a[i]移到最后面 会减少a[i]个逆序,增加N - 1 - a[i]个逆序 例如: 3 6 9 0 8 5 7 4 2 1 -->6 9 0 8 5 7 4 2 1 3 原因是3使得0 1 2的逆序共减少了3,但是由于4 5 6 7 8 9使自己的逆序增加了10 - 1 - 3 = 6 */ for (int i = 0; i < N - 1; i++) { ans += (N - 1 - a[i] - a[i]); minn = min(ans, minn); } printf("%d\n", minn); } return 0; }