今天做了一道关于逆序对的题目 于是就先学了一下归并排序
给定一个1-N的排列A1, A2, ... AN,如果Ai和Aj满足i < j且Ai > Aj,我们就称(Ai, Aj)是一个逆序对。
求A1, A2 ... AN中所有逆序对的数目。
Input第一行包含一个整数N。
第二行包含N个两两不同整数A1, A2, ... AN。(1 <= Ai <= N)
对于60%的数据 1 <= N <= 1000
对于100%的数据 1 <= N <= 100000
Output一个整数代表答案
5 3 2 4 5 1Sample Output
5
这是一开始的归并排序的实现
#include
#include
//OK
using namespace std;
int arr[50000+5];
void Merge (int arr[],int l,int m,int r)
{
const int left_length = m-l+1;
const int right_length = r-m;
int i,j,k;
int arr1[left_length+1],arr2[right_length+1];
for(i=0;i>n;
for(int i=0;i>arr[i];
int left = 0, right=n-1;
MergeSort(arr,left,right);
for(int i=left;i<=right;i++)
{
printf("%d",arr[i]);
if (i != n - 1)cout << endl;
}
return 0;
}
之后大概想了一下 逆序对产生的情况应该是 arr2插在arr1前面的时候(也就是 arr1[]>arr2[]这种情况 )在草稿纸上大概推了一下递归式是ans+=mid+1-i 可是放在这里答案不对....于是又百度了一下(下次弄谷歌...)用归并求逆序对的方法 发现别人的归并跟上面的还是有点不一样的...
#include
#include
//OK
using namespace std;
long arr[100000+5];
long temp[100000+5];
long ans=0;
void Merge (long arr[],long l,long m,long r)
{
long i=l,j=m+1,k=l;
while(i<=m&&j<=r)
{
if(arr[i]>arr[j])
{
temp[k]=arr[j];
k++,j++;
ans+=m-i+1;
}
else
{
temp[k]=arr[i];
i++,k++;
}
}
while(i<=m)
{
temp[k]=arr[i];
i++,k++;
}
while(j<=r)//两个while循环只会执行一次
{
temp[k]=arr[j];
k++,j++;
}
for(i=l;i<=r;i++)
arr[i]=temp[i];
}
void MergeSort(long arr[],long l,long r)
{
if(l==r)return ;
long m=(l+r)/2;
MergeSort( arr,l,m);
MergeSort (arr,m+1,r);
Merge(arr , l , m, r);//right
}
int main()
{
//int arr[]={2,8,9,10,4,5,6,7};
//t arr[]={2,8,4,9,10,5,6,7};
long n;
cin>>n;
for(int i=0;i>arr[i];
long left = 0, right=n-1;
//int arr[]={7,2,3,4};
//int left=0,right=3;
MergeSort(arr,left,right);
//for(int i=0;i
然后还有一个坑点就是数据范围 开始用int WA 改成long之后就AC了 //以后看清楚数据范围啊 还要背一下常用的范围
(噢百度了一下...int的范围与操作系统有关
百度了一下 求逆序对还可以用树状数组 目前明白原理但还没有实现(最近很多结构算法都是明白了原理但写不出来???)就下次再写吧