基础算法分治算法之1237:求排列的逆序数

定义

逆序数:一个数列nums[N],对任意两个数,如果前面的数大于后面的数,那么就称它们为一对逆序数。逆序数越大的排列与原始排列的差异度就越大。

题目

现给定1,2,…,n1,2,…,n的一个排列,求它的逆序数。

输入

第一行是一个整数nn,表示该排列有nn个数(n≤100000n≤100000)。
第二行是nn个不同的正整数,之间以空格隔开,表示该排列。

输出

输出该排列的逆序数。

代码

#include <iostream>
using namespace std;
long long temp[100001],a[100001],tot=0;
void merge_sort(int l,int r)//可计逆序数的排序 
{
 if(l>=r)return;//两侧相等或擦肩之后表示只剩一个元素了就退出 
 long long mid=(l+r)/2;//中点 
 merge_sort(l,mid);//左侧到中点排序 
 merge_sort(mid+1,r);//中点到右侧排序 
 //经过上述左右两侧分别排序后 
 long long p=l,i=l,j=mid+1;//p为新数组标志,i为左侧头部标志,j为右侧头部标志 
 while(i<=mid&&j<=r)//左右侧头部均未到达端尾时执行 
 {
  //比较左右侧头部,左侧大直接输入新数组,不计数;
  //右侧大放入新数组,且计数。
  //换角度,实际是在原数组中p与j通过mid-i+1(即j-p+1)次交换位置 
  //p=i+j-mid  ==>  j-p+1=mid-i+1;
  if(a[i]>a[j])
 {
   tot+=mid-i+1;
   temp[p++]=a[j++];
  }
  else
  temp[p++]=a[i++];
 }
 //左右两侧处理后会有一侧含有较大的剩余部分直接加入到尾部
 while(i<=mid)temp[p++]=a[i++];
 while(j<=r)temp[p++]=a[j++];
 for(i=l;i<=r;i++)
  a[i]=temp[i];//全部转入原数组
}
int main()
{
 long long n;
 cin>>n;
 for(int i=1;i<=n;i++)
 cin>>a[i];
 merge_sort(1,n);
 cout<<tot<<endl;
 return 0;
}

体会

分治算法的核心体现在将大问题细分为相似的小问题,通过相同的解决方法汇总,最终解决大问题;
如果发现计算超过计算时间,可以将流输入输出cin和cout换成格式化输入输出scanf,printf,因为格式化输入输出,更适合大数据处理。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值