原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=1394
求逆序数。
题目上来一看,发现直接暴力可过,复杂度O(n2),300+ms,代码简短得要命:
View Code
1 #include <stdio.h> 2 3 int a[5005]; 4 5 inline int min(int x, int y) 6 { 7 return x < y ? x : y; 8 } 9 10 int main() 11 { 12 int i, j, n, ans, m; 13 while(scanf("%d", &n) != EOF) 14 { 15 ans = 0; 16 for(i = 1; i <= n; i ++) 17 scanf("%d", &a[i]); 18 19 for(i = 1; i <= n; i ++) 20 for(j = i + 1; j <= n; j ++) 21 if(a[i] > a[j]) 22 ans ++; 23 m = ans; 24 for(i = 1; i < n; i ++) 25 ans = min(ans, m = m + n - a[i] - 1 - a[i]); 26 printf("%d\n", ans); 27 } 28 return 0; 29 }
其实这道题复杂度都耗在了第一次求总逆序数上了,后来想想,发现可以用nlog(n)的归并排序搞,15~30ms。
View Code
1 #include <stdio.h> 2 #define N 5005 3 int a[N], b[N], c[N]; 4 5 inline int min(int x, int y) 6 { 7 return x < y ? x : y; 8 } 9 10 int cal(int s, int t) 11 { 12 int i, j, k, mid; 13 int res; 14 if(t - s == 1) 15 return 0; 16 mid = (s + t) >> 1; 17 res = cal(s, mid) + cal(mid, t); 18 i = s, j = mid, k = s; 19 while(i < mid && j < t) 20 { 21 if(a[i] <= a[j]) 22 b[k ++] = a[i ++], res += j - mid; 23 else 24 b[k ++] = a[j ++]; 25 } 26 while(i < mid) b[k ++] = a[i ++], res += j - mid; 27 while(j < t) b[k ++] = a[j ++]; 28 for(i = 0; i < t - s; i ++) 29 a[s + i]= b[s + i]; 30 return res; 31 } 32 33 int main() 34 { 35 int i, n, ans, m; 36 while(scanf("%d", &n) != EOF) 37 { 38 for(i = 1; i <= n; i ++) 39 { 40 scanf("%d", &a[i]); 41 c[i] = a[i]; 42 } 43 ans = cal(1, n + 1); 44 m = ans; 45 for(i = 1; i < n; i ++) 46 ans = min(ans, m = m + n - c[i] - 1 - c[i]); 47 printf("%d\n", ans); 48 } 49 return 0; 50 }
其实我是想用线段树写的,30ms。
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #define lson (cur << 1) 4 #define rson (cur << 1 | 1) 5 #define N 5005 6 7 int tree[N << 2], a[N]; 8 9 inline int min(int x, int y) 10 { 11 return x < y ? x : y; 12 } 13 14 void pushup(int cur) 15 { 16 tree[cur] = tree[lson] + tree[rson]; 17 } 18 19 void query(int cur, int l, int r, int x, int y, int &ans) 20 { 21 if(l >= x && r <= y) 22 { 23 ans += tree[cur]; 24 return ; 25 } 26 int mid = (l + r) >> 1; 27 if(mid >= x) 28 query(lson, l, mid, x, y, ans); 29 if(mid + 1 <= y) 30 query(rson, mid + 1, r, x, y, ans); 31 } 32 33 void update(int cur, int l, int r, int loc) 34 { 35 if(l == r) 36 { 37 tree[cur] = 1; 38 return ; 39 } 40 int mid = (l + r) >> 1; 41 if(mid >= loc) 42 update(lson, l, mid, loc); 43 else 44 update(rson, mid + 1, r, loc); 45 pushup(cur); 46 } 47 48 int main() 49 { 50 int n, i, v, ans, sum; 51 while(scanf("%d", &n) != EOF) 52 { 53 memset(tree, 0, sizeof tree); 54 for(sum = 0, i = 1; i <= n; i ++) 55 { 56 scanf("%d", &a[i]); 57 v = 0; 58 query(1, 1, n, a[i] + 1, n, v); 59 sum += v; 60 update(1, 1, n, a[i]); 61 } 62 ans = sum; 63 for(i = 1; i < n; i ++) 64 ans = min(ans, sum = sum + n - a[i] - 1 - a[i]); 65 printf("%d\n", ans); 66 } 67 return 0; 68 }