787 归并排序基础
#include <iostream>
using namespace std;
const int N = 100010;
int temp[N],a[N],n;
void merge_sort(int a[], int l, int r){
if(l >= r)return;
int mid = (l + r) >> 1;
merge_sort(a, l, mid);
merge_sort(a, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r){
if(a[i] < a[j]) temp[k++] = a[i++];
else temp[k++] = a[j++];
}
while (i <= mid) temp[k++] = a[i++];
while (j <= r) temp[k++] = a[j++];
k = 0;
for(int i = l; i<=r; i++ ) a[i]=temp[k++];
}
int main (){
scanf("%d", &n);
for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
merge_sort(a, 0, n-1);
for(int i = 0; i < n; i++ )printf("%d ",a[i]);
return 0;
}
788 逆序对的数量
地址:https://www.acwing.com/problem/content/790/
#include <iostream>
using namespace std;
const int N = 100010;
int temp[N];
int a[N],n;
long long reverseNum( int l, int r){
//在归并排序的过程中,计算逆序对
if(l >= r) return 0;
int mid = l + r >> 1;
long long num = reverseNum(l, mid) + reverseNum(mid + 1, r);//
int k=0, i = l, j = mid + 1;
while(i <= mid && j <= r){
if(a[i] <= a[j]){//在该步骤判断是否逆序
temp[k++] = a[i++];
}else{
temp[k++] = a[j++];
num += mid - i + 1;
}
}
while(i <= mid) temp[k++] = a[i++];
while(j <= r) temp[k++] = a[j++];
for(int i = l,k = 0; i <= r; i++, k++)a[i]=temp[k];
return num;
}
int main(){
cin >> n;
for(int i = 0; i < n; i++ ) cin >> a[i];
cout << reverseNum(0, n-1) << endl;
return 0;
}
分析
归并算法的基本思想 左右两组进行对比
,即分治算法。在每次循环的时候,左右两组均为有序。自底向上,最底层的两组,即两个数字m和n,左右两组各有一个数字,这自然是有序的。自此由下往上,使用归并算法,使得每组均有序。
在求逆序数的过程中,我们只需关注,左右两组的数字作比较,即左边的某一个数字a[i]开始大于右边的a[j],此时i到mid均大于j。
总结
思想简单,但理解起来略有难度,比较绕