题解一:使用树状数组在O(nlogn)的时间内解决了这个问题,
题解二:使用数列上的分治法进行统计,可以将数列A分为两半得到数列B和数列C。于是,数列A中所有的逆序对必然是下面三者之一
1.i,j都属于数列B的逆序对(i,j)
2.i,j都属于数列C的逆序对(i,j)
3.i属于数列B而j属于数列C的逆序对(i,j)
所以,只要分别统计这三种逆序对,再把结果相加到一起就行了,对于1和2通过递归求得,对于3,我们可以统计数列C中的每个数字,统计时在数列B中比它大的数字的个数,再把结果相加起来就好了,这就可以通过在归并排序的同时进行统计得到。
每次递归长度都会减半,所以递归的深度为O(logn),而每一层总的操作都是O(n),所以总的复杂度为O(nlogn).
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int>A;
ll merge_count(vector<int>&a)
{
int n=a.size();
if(n<=1){
return 0;
}
ll cnt=0;
vector<int>b(a.begin(),a.begin()+n/2);
vector<int>c(a.begin()+n/2,a.end());
cnt+=merge_count(b);
cnt+=merge_count(c);
int ai=0,bi=0,ci=0;
while(ai<n){
if(bi<b.size()&&(ci==c.size()||b[bi]<=c[ci])){
a[ai++]=b[bi++];
}else{
cnt+=n/2-bi;
a[ai++]=c[ci++];
}
}
return cnt;
}
void solve()
{
printf("%lld\n",merge_count(A));
}
int main()
{
//输入A
solve();
return 0;
}