zcmu:1205: 正序數+1203: 逆序數(歸併排序)
這兩道題目可以說是一毛一樣的,就放在一起說一下。用到了一個歸併排序的內容,我搜了幾篇部落格學習了下歸併排序,寫得都很好,基本認真看兩遍一定能看明白了
***************歸併排序詳述***************
1203: 逆序數
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 626 Solved: 142
[Submit][Status][Web Board]Description
在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數不小於後面的數,那麼它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序數是4。給出一個整數序列,求該序列的逆序數。
Input
多組測試資料
每組測試資料分兩行,第一行一個正整數n(n <= 50000)
第二行有n個元素( 0 <= A[i] <= 10^9)
Output
每組測試資料輸出一行表示逆序數
Sample Input
4 2 4 3 1 3 1 1 1
Sample Output
4 3
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <list> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <iostream> #define mem(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=5e5+5; ll a[maxn],b[maxn]; ll cou=0; void merges(ll a[],int start,int mid,int en) { int i=start,j=mid+1,k=start; while(i<=mid && j<=en) { if(a[i]<a[j]) { b[k++]=a[i++]; } else { cou+=j-k; b[k++]=a[j++]; } } while(i<=mid) { b[k++]=a[i++]; } while(j<=en) { b[k++]=a[j++]; } for(i=start;i<=en;i++) { a[i]=b[i]; } } void mergesort(ll a[],int start,int en) { if(start<en) { int mid=(start+en)/2; mergesort(a,start,mid); mergesort(a,mid+1,en); merges(a,start,mid,en); } } int main(int argc, char const *argv[]) { int n; while(cin>>n) { cou=0; for(int i=0;i<n;i++) scanf("%lld",&a[i]); mergesort(a,0,n-1); cout<<cou<<endl; } return 0; }
1205: 正序數
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 280 Solved: 89
[Submit][Status][Web Board]Description
在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序數是4。
**相對於逆序數而言,當然有正序數,即:在一個排列中,如果一對數的前後位置與大小順序相同,即前面的數小於後面的數,那麼它們就稱為一個正序。一個排列中正序的總數就稱為這個排列的正序數。
如2 4 3 1中,2 4,2 3是正序,正序數是2。
Input
多組測試資料
每組測試資料分兩行,第一行一個正整數n(n <= 50000)
第二行有n個元素( 0 < A[i] <= 500000)
Output
每組測試資料輸出一行表示逆序數
Sample Input
4 2 4 3 1
Sample Output
2
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll a[maxn],b[maxn];
ll cou=0;
void merges(ll a[],int start,int mid,int en)
{
int i=start,j=mid+1,k=start;
while(i<=mid && j<=en)
{
if(a[i]>=a[j])//這裡改下就好了~~其他都跟上面一樣的
b[k++]=a[i++];
else
{
cou += j-k;
b[k++]=a[j++];
}
}
while(i<=mid)
{
b[k++]=a[i++];
}
while(j<=en)
{
b[k++]=a[j++];
}
for(i=start;i<=en;i++)
{
a[i]=b[i];
}
}
void mergesort(ll a[],int start,int en)
{
if(start<en)
{
int mid=(start+en)/2;
mergesort(a,start,mid);
mergesort(a,mid+1,en);
merges(a,start,mid,en);
}
}
int main(int argc, char const *argv[])
{
int n;
while(cin>>n)
{
cou=0;
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
mergesort(a,0,n-1);
cout<<cou<<endl;
}
return 0;
}