使用归并排序实现。
线段树还不会。
POJ 1804 裸题
#include <stdio.h> #include <stdlib.h> int num[1001]; int count; void merge(int left, int mid, int right) { int temp[1001]; int i = left, j = mid + 1, k = left; while (i <= mid&&j <= right) { if (num[i] > num[j]) { count = count + mid - i + 1; temp[k++] = num[j++]; } else temp[k++] = num[i++]; } while (i <= mid) temp[k++] = num[i++]; while (j <= right) temp[k++] = num[j++]; for (i = left; i <= right; i++) num[i] = temp[i]; } void mergeSort(int left, int right) { if (left < right) { int mid = (left + right) / 2; mergeSort(left, mid); mergeSort(mid + 1, right); merge(left, mid, right); } } int main() { int n, i; scanf("%d", &n); int m, j; for (i = 1; i <= n; i++) { scanf("%d", &m); for (j = 1; j <= m; j++) scanf("%d", &num[j]); count = 0; mergeSort(1, m); printf("Scenario #%d:\n", i); printf("%d\n\n", count); } return 0; }
上交OJ 1219 变形题
用到了c++的二分函数。感觉STL还是强。但是有的学校不允许使用。这道题调了很长时间。
注意最后的结果用int会溢出,导致错误。
#include <stdio.h> #include <stdlib.h> #include <algorithm> using namespace std; int num[200001]; long long cnt; void merge(int left, int mid, int right) { int temp[200001]; int i = left, j = mid + 1, k = left; while (i <= mid&&j <= right) { if (num[i] > num[j]) { /* tle int t; for (t = i; t <= mid; t++) { if (num[t] > (2 * num[j])) cnt++; }*/ // 下面两行代码是关键 int pos = upper_bound(num + i, num + (mid + 1), 2 * num[j]) - num; cnt += mid - pos + 1; temp[k++] = num[j++]; } else temp[k++] = num[i++]; } while (i <= mid) temp[k++] = num[i++]; while (j <= right) temp[k++] = num[j++]; for (i = left; i <= right; i++) num[i] = temp[i]; } void mergeSort(int left, int right) { if (left < right) { int mid = (left + right) / 2; mergeSort(left, mid); mergeSort(mid + 1, right); merge(left, mid, right); } } int main() { int m, j; while (EOF != scanf("%d", &m)) { for (j = 1; j <= m; j++) scanf("%d", &num[j]); cnt = 0; mergeSort(1, m); printf("%lld\n", cnt); } return 0; }