逆序数的性质。
1. 暴力解
#include <stdio.h> #define MAXNUM 5005 int a[MAXNUM]; int main() {
int n;
int i, j, sum, min; while (scanf("%d", &n) != EOF) {
for (i=; i<n; ++i)
scanf("%d", &a[i]);
sum = ;
for (i=; i<n; ++i) {
for (j=i+; j<n; ++j)
if (a[j] < a[i])
++sum;
}
min = sum;
for (i=; i<n; ++i) {
sum += n - - a[i]*;
if (sum < min)
min = sum;
//printf("%d\n", sum);
}
printf("%d\n", min);
} return ;
}
2. 线段树。需要理解如何求逆序数。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; #define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1 const int maxn = ; int nums[maxn<<];
int a[maxn]; void PushUP(int rt) {
nums[rt] = nums[rt<<] + nums[rt<<|];
} void build(int l, int r, int rt) {
nums[rt] = ;
if (l == r) return;
int m = (l+r)>>;
build(lson);
build(rson);
} void update(int p, int l, int r, int rt) {
if (l == r) {
nums[rt] = ;
return ;
}
int m = (l+r)>>;
if (p <= m)
update(p, lson);
else
update(p, rson);
PushUP(rt);
} int query(int ll, int rr, int l, int r, int rt) {
if (ll<=l && rr>=r) {
return nums[rt];
}
int m = (l+r)>>;
int ret = ;
if (ll <= m)
ret += query(ll, rr, lson);
if (rr > m)
ret += query(ll, rr, rson); return ret;
} int main() {
int n;
int i, sum, min; while (scanf("%d", &n) != EOF) {
build(, n-, );
sum = ;
for (i=; i<n; ++i) {
scanf("%d", &a[i]);
sum += query(a[i], n-, , n-, );
update(a[i], , n-, );
//printf("%d: sum=%d\n", i, sum);
}
min = sum;
for (i=; i<n; ++i) {
sum += n - - a[i]*;
if (sum < min)
min = sum;
}
printf("%d\n", min);
} return ;
}