给你一个未排序的数列,每次可换相邻的两个数,问换成一个正常升序后,所需要的次数。第一反应就是求逆序列,看了看时间给了7000ms,感觉水过去够了,于是水了一发,果不其然的超时了.....后来发现500000,o(n*n),根本水不过去,后来搜了一搜, 发现用归并排序可以做。于是做了
这是归并排序
void mergearray(int a[], int first, int mid, int last, int temp[]) { int i = first, j = mid + 1; int m = mid, n = last; int k = 0; while (i <= m && j <= n) { if (a[i] <= a[j]) temp[k++] = a[i++]; else temp[k++] = a[j++]; } while (i <= m) temp[k++] = a[i++]; while (j <= n) temp[k++] = a[j++]; for (i = 0; i < k; i++) a[first + i] = temp[i]; } void mergesort(int a[], int first, int last, int temp[]) { if (first < last) { int mid = (first + last) / 2; mergesort(a, first, mid, temp); //左边有序 mergesort(a, mid + 1, last, temp); //右边有序 mergearray(a, first, mid, last, temp); //再将二个有序数列合并 } } bool MergeSort(int a[], int n) { int *p = new int[n]; if (p == NULL) return false; mergesort(a, 0, n - 1, p); delete[] p; return true; }
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; long long num[500005]; long long temp[500005]; int n; long long ans; void merge(int low, int mid, int high) { int i = low, j = mid + 1, k = low; while (i <= mid && j <= high) { if (num[i] <= num[j]) { temp[k++] = num[i++]; } else { ans += j - k ; temp[k++] = num[j++]; } } while (i <= mid) temp[k++] = num[i++]; while (j <= high) temp[k++] = num[j++]; for (i = low; i <= high; ++i) { num[i] = temp[i]; } } void mergeSort(int a, int b) { if (a < b) { int mid = (a + b) / 2; mergeSort(a, mid); mergeSort(mid + 1, b); merge(a, mid, b); } } int main() { while (scanf("%d", &n) != EOF && n > 0) { ans = 0; for (int i = 0; i < n; ++i) { scanf("%lld", num + i); } mergeSort(0, n - 1); printf("%lld\n", ans); } return 0; }