1.题目
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。
即输出P%1000000007
2.基本思路
考察的是归并排序,计算次数时候是在执行合并操作的时候(合并两个有序的表)。
设数组为A,将p~q和q+1~r
之间的元素合并。设s=p,t=q+1,则逆序对数目计算如下
- 如果A[s]<=A[t],则不计数
- 如果A[s]>A[t],则count=count+ q-s+1,(因为此时指针s指向的位置后面的元素都比A[t]要打,故总共有
q-s+1
个逆序对)
3.代码如下
- 代码1
void Merge(vector<int>&A,int p,int q,int r,unsigned int &allcount)
{ // 合并数组 p~q 和 q到r
int s,t,k;
int count=0;
s=p;
t=q+1;
k=0;
vector<int> B(r-p+1,0);
while(s<=q && t<=r)
{
if(A[t]>=A[s])
{
B[k++]=A[s++];
}else {
B[k++]=A[t++];
if(count>1000000007)
count =count%1000000007;
count += q-s+1;
}
}
if(s==(q+1)){ // 说明s到头了
for(;t<=r;++t)
B[k++]=A[t];
}else{// 说明t到头了
for(;s<=q;++s)
B[k++]=A[s];
}
k=0;
s=p;
while(s<=r) // 这里将r写成了t,怪不得出错了
A[s++]=B[k++];
allcount=allcount%1000000007;
allcount=(allcount+count)%1000000007;
}
void MergeSort(vector<int>&A,int low,int high,unsigned int &allcount)
{
int mid;
if(low<high)
{
mid=(low+high)/2;
MergeSort(A,low,mid,allcount);
MergeSort(A,mid+1,high,allcount);
Merge(A,low,mid,high,allcount);
}
}
int InversePairs(vector<int> data) {
if(data.size()<=1)
return 0;
unsigned int allcount=0;
MergeSort(data,0,data.size()-1,allcount);
return allcount;
}
- 代码2
int InversePairs2(vector<int> data) { //
if(data.size()<=1)
return 0;
unsigned int allcount=0;
int t,s,i,n;
t=1;
n=data.size();
while(t<data.size())
{
s=t;
t=2*s;
i=0;
while( (i+t)<=n)
{
Merge(data,i,i+s-1,i+t-1,allcount);
i=i+t;
}
if( (i+s)<n)
Merge(data,i,i+s-1,n-1,allcount);
}
return allcount;
}