题目:http://acm.hdu.edu.cn/showproblem.php?pid=2443
这个题目尝试了很多种方法都过不去,上网查了一下网友们的的思路,竟然和逆序对数有关系!!
题目大意:
有n个士兵,他们都有各自的分数,有一项任务需要完成,为了能够确保合作更默契,他们的分数要差不多,所以有一个水平控制即平均数,所选的一组士兵的平均成绩必须大于该平均数。
问一共能选出多少组士兵能够完成该项任务?
思路:
求逆序对数。归并排序可以用来求逆序对数,这个没毛病。
代码如下:
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 void combine_sortd_list(int* to, int* sub1, int sz1, int* sub2, int sz2); 5 void merge_sort(int* lst, int sz); 6 const int MAX = 1e5 + 5; 7 int arr[MAX]; 8 long long int ans; 9 int main() 10 { 11 int Group, N, A; 12 cin >> Group; 13 while (Group--) 14 { 15 memset(arr, 0, sizeof arr); 16 cin >> N >> A; 17 for (int j, i = N-1; i >=0; --i) 18 { 19 cin >> j; 20 arr[i] = j - A + arr[i + 1]; 21 } 22 ans = 0; 23 merge_sort(arr, N + 1); //归并求逆序数 24 cout << ans << endl; 25 } 26 } 27 void merge_sort(int* lst, int sz) 28 { 29 static int tmp[MAX]; 30 if (sz <= 1)return; 31 int* l = lst; 32 int lsz = (sz + 1) / 2; 33 int* r = l + lsz; 34 int rsz = sz / 2; 35 merge_sort(l, lsz); 36 merge_sort(r, rsz); 37 combine_sortd_list(tmp, l, lsz, r, rsz); 38 for (int i = 0; i < sz; ++i)lst[i] = tmp[i]; 39 } 40 void combine_sortd_list(int*to, int* sub1, int sz1, int* sub2, int sz2) 41 { 42 int i = 0, j = 0, k = 0; 43 while (i < sz1&&j < sz2) 44 if (sub1[i] <= sub2[j])to[k++] = sub1[i++]; 45 else 46 { 47 ans += sz1 - i; 48 to[k++] = sub2[j++]; 49 } 50 while (i < sz1)to[k++] = sub1[i++]; 51 while (j < sz2)to[k++] = sub2[j++]; 52 }
由公式推导解析题目意图:http://blog.csdn.net/scorpiocj/article/details/6227528
感谢您的阅读,生活愉快~