【HDOJ】1394 Minimum Inversion Number
逆序数的性质。
1. 暴力解
1 #include <stdio.h> 2 3 #define MAXNUM 5005 4 5 int a[MAXNUM]; 6 7 int main() { 8 int n; 9 int i, j, sum, min; 10 11 while (scanf("%d", &n) != EOF) { 12 for (i=0; i<n; ++i) 13 scanf("%d", &a[i]); 14 sum = 0; 15 for (i=0; i<n; ++i) { 16 for (j=i+1; j<n; ++j) 17 if (a[j] < a[i]) 18 ++sum; 19 } 20 min = sum; 21 for (i=0; i<n; ++i) { 22 sum += n - 1 - a[i]*2; 23 if (sum < min) 24 min = sum; 25 //printf("%d\n", sum); 26 } 27 printf("%d\n", min); 28 } 29 30 return 0; 31 }
2. 线段树。需要理解如何求逆序数。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 #define lson l, m, rt<<1 7 #define rson m+1, r, rt<<1|1 8 9 const int maxn = 5005; 10 11 int nums[maxn<<2]; 12 int a[maxn]; 13 14 void PushUP(int rt) { 15 nums[rt] = nums[rt<<1] + nums[rt<<1|1]; 16 } 17 18 void build(int l, int r, int rt) { 19 nums[rt] = 0; 20 if (l == r) return; 21 int m = (l+r)>>1; 22 build(lson); 23 build(rson); 24 } 25 26 void update(int p, int l, int r, int rt) { 27 if (l == r) { 28 nums[rt] = 1; 29 return ; 30 } 31 int m = (l+r)>>1; 32 if (p <= m) 33 update(p, lson); 34 else 35 update(p, rson); 36 PushUP(rt); 37 } 38 39 int query(int ll, int rr, int l, int r, int rt) { 40 if (ll<=l && rr>=r) { 41 return nums[rt]; 42 } 43 int m = (l+r)>>1; 44 int ret = 0; 45 if (ll <= m) 46 ret += query(ll, rr, lson); 47 if (rr > m) 48 ret += query(ll, rr, rson); 49 50 return ret; 51 } 52 53 int main() { 54 int n; 55 int i, sum, min; 56 57 while (scanf("%d", &n) != EOF) { 58 build(0, n-1, 1); 59 sum = 0; 60 for (i=0; i<n; ++i) { 61 scanf("%d", &a[i]); 62 sum += query(a[i], n-1, 0, n-1, 1); 63 update(a[i], 0, n-1, 1); 64 //printf("%d: sum=%d\n", i, sum); 65 } 66 min = sum; 67 for (i=0; i<n; ++i) { 68 sum += n - 1 - a[i]*2; 69 if (sum < min) 70 min = sum; 71 } 72 printf("%d\n", min); 73 } 74 75 return 0; 76 }