之前一直以为归并排序基本用不上(毕竟都有sort了),就没很认真学,直到碰到了这题才发现没有用不到的算法0.0,然后又回头去学了。
归并排序就是先把一个数组分为每份只有一个数字的方法,然后再每两组一排序,刚好可以完美解决这个问题,毕竟这个问题就是小的数字排序的时候看看经过了多少比自己大的数字。
我们以45132为例子来说
1.首先分为4 5 1 3 2 一共5个数字
2.然后每两组一划分 就是45 13 2
3.再然后就是1345 2
4.最后就是12345啦。
很明显前两组排列的时候都没有出现小的数字排到大的数字前,答案我们用ans来表示就是0
到了第三组就很容易发现有两个数字跑到了比自己要大的数字前面去了ans+=2+2;
第四组2跑到了三前面,经历了三个比他大的数字就是ans+=3;
所以ans=7就是我们想要的结果了。
样例自己试试就知道对不对了。
#include<iostream>
using namespace std;
const int MAX = 500010;//题目的数据范围在MAX这么大。
int a[MAX];
int temp[MAX];
long long ans;//十年oi一场空,不开longlong见祖宗。(其实得算一下题目的数据)
void merge_sort(int l,int r){
if(l==r)
return ;
int mid = (l+r)>>1;//(等价于(l+r)/2)
merge_sort(l,mid);
merge_sort(mid+1,r);
//模拟我说的步骤
for(int i=l;i<=r;i++)
temp[i] = a[i];
int i1 = l, i2 = mid+1;//l1指向第一个数组的头部,i2指向第二个数组的头部
for(int i=l;i<=r;i++){
if(i1>mid)//当第一个数组用完了以后,只需要把第二个数组全部输进去就可以了
a[i] = temp[i2++];
else if(i2>r)//同上
a[i] = temp[i1++];
else if(temp[i1]<=temp[i2])//这个情况是不需要计算ans的值的
a[i] = temp[i1++];
else {//当发现有数字想跑到比他大的数字前面去的时候,就需要计算ans的值
a[i] = temp[i2++];
ans+=mid-i1+1;//如果这个数字比temp【i1】小,那他一定比(i1,mid]都要小,因为之前排序
}
}
}
int main(void){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
merge_sort(1,n);
cout<<ans;
return 0;
}