基于归并排序
归并排序是一种分治算法,其基本思路可以简述为:
- 分解:将原始数组分解成若干个子数组,直到每个子数组只有一个元素为止。
- 解决:将相邻的子数组两两合并并排序,直到所有子数组合并成一个数组。
- 合并:合并过程中,比较两个子数组的第一个元素,将较小(或较大)的元素放入新数组中,直到两个子数组都被遍历完毕。
class Solution {
public:
int tmp[50000];
int mergeSort(vector<int>& nums, int left, int right) {
if (left >= right) return 0;
int mid = left + right >> 1;
int res = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
int k = 0, i = left, j = mid + 1;
while(i <= mid && j <= right) {
if (nums[i] <= nums[j]) {
tmp[k++] = nums[i++];
} else {
tmp[k++] = nums[j++];
res += (mid - i + 1);
}
}
while(i <= mid) {
tmp[k++] = nums[i++];
}
while(j <= right) {
tmp[k++] = nums[j++];
}
int t = 0;
while(left <= right) {
nums[left++] = tmp[t++];
}
return res;
}
int reversePairs(vector<int>& nums) {
return mergeSort(nums, 0, nums.size() - 1);
}
};
P1980逆序对
题目链接
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + 10;
int a[N], tmp[N];
int n;
ll cnt;
void merge(int left, int mid, int right) {
int i = left, j = mid + 1, k = 0;
while(i <= mid && j <= right) {
if (a[i] > a[j]) {
tmp[k++] = a[j++];
cnt += (mid - i + 1);
} else {
tmp[k++] = a[i++];
}
}
while(i <= mid)
tmp[k++] = a[i++];
while(j <= right)
tmp[k++] = a[j++];
k = 0;
while(left <= right)
a[left++] = tmp[k++];
}
void mergeSort(int left, int right) {
if (left >= right) return;
int mid = (left + right) >> 1;
mergeSort(left, mid);
mergeSort(mid + 1, right);
merge(left, mid, right);
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i ++)
scanf("%d", &a[i]);
mergeSort(0, n - 1);
printf("%ld\n", cnt);
return 0;
}