分治把一个任务分解成多个规模更小的任务,能显著改善解决问题的效率。归并排序与快速排序是其典型应用,变形问题有排列的逆序数与输出前k大的数。
一、排列的逆序数
1.问题简述
考虑1,2,…,n的排列 i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij> ik, 那么就称(ij,ik)是这个排列的一个逆序。一个排列含有逆序的个数称为这个排列的逆序数。
现给定1,2,…,n的一个排列,求它的逆序数。
输入
第一行是一个整数n,表示该排列有n个数(n <= 100000)。
第二行是n个不同的正整数,之间以空格隔开,表示该排列。
输出
输出该排列的逆序数。
样例输入
6
2 6 3 4 5 1
样例输出
8
注意结果可能超过int的范围,需要用long long存储。
2.问题分析
把序列分成前后两部分,则
整个序列的逆序数=左序列的逆序数+右序列的逆序数+左右间相互形成的逆序数
与归并排序的思想完全一致,在归并排序的基础上添加计数逆序数的功能即可。
3.源代码
#include <iostream>
using namespace std;
long long cnt=0; //注意题目提示
void MergeSort(int a[],int s,int e,int temp[]);//归并排序
void Merge(int a[],int s,int m,int e,int tem[]);//合并分别排序后的左右区间
//统计逆序数也在该区间
int main()
{
int n,a[100000],temp[100000];
cin>>n;
for (int i=0;i<n;++i)
cin>>a[i];
MergeSort(a,0,n