这道题主要就是第一周的课程的内容的训练,训练的是对归并排序(margesort)的运用;
题目:
题目内容:
在一個N個數字的序列S裡,當S[i] > S[j] 且 i < j的時候,我們說(i ,j)是一個逆序數對。
Hint : 利用歸併排序法計算一個序列裡有多少逆序數對。
Hint : 思考一下在merge的過程,怎麼找到答案!
Hint : 直接使用兩層迴圈來找答案的話會超過系統時間限制。
输入格式:
只有一筆測資,第一行為一個數字N,代表接下來有N行,每行有一個數字。這N個數字都會相異。
數字範圍:
0 < N < 20000
输出格式:
輸出一行數字,該序列的逆序數對個數。
输入样例:
7
4
2
6
1
5
3
0
输出样例:
14
题解:这道题非常巧妙的利用了mergesort分而治之的思想,基本解法就是重新写了一次mergesort然后加了一点小技巧;
代码如下:
code:
#include <iostream>
#include <cstdio>
using namespace std;
const int N=100005;
int ans=0;
void Merge(int a[], int l , int m , int r )
{
int i=l;
int j=m+1;
int k=l;
int b[N];
while(i<=m &&j<=r)
{
if(a[i]<=a[j])
{
b[k++]=a[i++];
}
else
{
b[k++]=a[j++];
ans+=j-k;
}
}
if(i>m)
{
for(int p=j; p<=r; p++)
{
b[k++]=a[p];
}
}
else
{
for(int p=i; p<=m; p++)
{
b[k++]=a[p];
}
}
for(int q=l; q<=r; q++)
{
a[q]=b[q];
}
return;
}
void mergesort(int a[],int l, int r)
{
if(l<r)
{
int m=(l+r)/2;
mergesort(a,l,m);
mergesort(a,m+1,r);
Merge(a,l,m,r);
}
return ;
}
int main()
{
int arr[N];
int n;
cin>>n;
for(int i=0; i<n; i++)
scanf("%d",&arr[i]);
mergesort(arr,0,n-1);
cout<<ans<<endl;
return 0;
}
去掉“ans+=j-k"他就是一个归并排序;
归并排序作为我学的第二个算法,值得记录一下~