题目:
给你N个数组成的序列,求这个序列的逆序数一共有多少个。这个序列个数不超过100000.
解题思路:
很经典的一个问题,解决方法有两种:第一种方法是归并排序,第二种方法是树状数组。
如果我们要枚举的话,复杂度为o(n*n),铁定TLE,所以要考虑更高效的算法。归并操作中,当取到右边集合的第i个元素时,左边集合中元素的个数就是这个元素的逆序数,以此类推,把右边集合全部的逆序数求出来,求和,就是这个序列的逆序数.
#include<iostream>
#include<time.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define N 15
int sum=0;
void merge(int a[],int l,int m,int r)
{
int k=0,begin1,begin2,end1,end2;
int *t;
begin1=l;
end1=m;
begin2=m+1;
end2=r;
t= new int[r-l+1];
for(k=0;begin1<=end1&&begin2<=end2;)
{
if(a[begin1]<=a[begin2]){
t[k]=a[begin1++];
}
else{
t[k]=a[begin2++];
sum+= m-begin1+1;
}
k++;
}
while(begin1<=end1||begin2<=end2)
{
if(begin1<=end1){
t[k++] = a[begin1++];
}
if(begin2<=end2){
t[k++]=a[begin2++];
}
}
for(int i=0;i<=(r-l);i++)
{
a[l+i] = t[i];
}
delete []t;
}
void merge_sort(int a[], int l,int r)
{
if(l>=r) return;
else{
int m=(l+r)/2;
merge_sort(a,l,m);
merge_sort(a,m+1,r);
merge(a,l,m,r);
}
}
void print(int a[])
{
int i=0;
while(i<N)
{
cout<<a[i]<<" ";
i++;
}
cout<<endl;
}
int main()
{
int a[N];
srand(time(0));
for(int i=0;i<N;i++)
{
a[i]=rand()%(N*15);
}
merge_sort(a,0,N-1);
print(a);
cout<<"sum:"<<sum<<endl;
return 0;
}