Sort 归并排序求逆序对

来源:互联网 发布:java开发一年工作经验 编辑:程序博客网 时间:2024/06/06 01:35

Time limit per test: 4.0 seconds

Time limit all tests: 4.0 seconds

Memory limit: 256 megabytes

You want to process a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order.

Input

There are several test cases, please process till EOF.

For each test case, the first line contains integer n (1n105). The second line contains n space-separated integers a1,a2,,an (1ai109).

Output

For each test case, output the minimum times of swapping in one line.

Examples

input
21 2
output
0

题意: 求逆序对。

分析:

首先理解归并排序。 给你一个混乱的序列,先将它分半变成两个序列,分别对每个序列排序,然后合并两个序列。  合并的操作就是每次比较两个序列的最小值,然后将最小值放到新的序列中,并再原序列删除那个最小值。

具体操作就是不断二分,至到每个序列只包含一个元素,这样就可以默认当前元素已经排好序了,再进行合并即可。

那怎么求逆序对呢? 对于每个即将要合并两个序列,我们可以知道在两个序列的内部是不存在逆序对的(因为已经是排好序的)。所以逆序对只存在两个序列之间。举例来说

假设第一个序列为 3 4 5       第二个序列为 1  2

那么对与合并操作,肯定要先比较 3 和 1 的大小,然后将1放到新的序列中。 可以因为3比1大,所以这是一个逆序对,同样的,对于第一个序列中所有大于3的元素,每一个都可以和1构成逆序对,所以cnt每次要加所有大于等于3的元素的个数。

具体看代码。

#include<iostream>#include<cstdio>#include<string.h>#include<math.h>#include<string>#include<map>#include<set>#include<vector>#include<algorithm>#include<queue>#include<iomanip>using namespace std;const int INF = 0x3f3f3f3f;const int NINF = 0xc0c0c0c0;const int maxn = 100005;long long cnt = 0;void merge_sort(int *A,int *T,int beg,int en){    if(en-beg>1){        int mid = beg + (en-beg)/2;        int s1 = beg,s2 = mid;        int e1 = mid,e2 = en;        int pos = beg;        merge_sort(A,T,s1,e1);//缩小问题规模        merge_sort(A,T,s2,e2);        while(s1<e1 && s2<e2){            if(A[s1] > A[s2]){                cnt += e1-s1;//只需要加一个cnt,即可求出逆序对的个数。                T[pos++] = A[s2++];            }            else T[pos++] = A[s1++];        }        while(s1 < e1){//若出现一个序列为空,则将另一个序列的元素依次放入新的序列。            T[pos++] = A[s1++];        }        while(s2 < e2){            T[pos++] = A[s2++];        }        for(pos = beg;pos<en;pos++)//将每次合并好的序列放入原始序列(保证规模更大时,两个序列都是有序的)            A[pos] = T[pos];    }}int main(){    int A[maxn];//原始序列    int T[maxn];//辅助序列    int n;    while(cin >> n){        memset(T,0,sizeof(T));        for(int i=0;i<n;i++){            cin >> A[i];        }        cnt = 0 ;        merge_sort(A,T,0,n);        cout << cnt << endl;    }}


0 0