归并法求逆序数

求逆序数

时间限制: 2000 ms  |  内存限制: 65535 KB
难度: 5
 
描述

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。

比如 1 3 2 的逆序数就是1。

 
输入
第一行输入一个整数T表示测试数据的组数(1<=T<=5) 每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000) 随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素。
数据保证在多组测试数据中,多于10万个数的测试数据最多只有一组。
输出
输出该数列的逆序数
样例输入
2

2

1 1

3

1 3 2
样例输出
0

1
 1 //可以直接双重for循环 

 2 #include<iostream>

 3 #include<cstdio>

 4 #include<stdlib.h>

 5 #define N 1000010

 6 using namespace std;

 7 long long ans;

 8 int a[N];

 9 

10 void merge(int s1,int e1,int s2,int e2)

11 {

12     int p1,p2,p;

13     int* temp = new int[e2-s1+5];

14     p=0;p1=s1;p2=s2;

15     while(p1<=e1&&p2<=e2)

16     {

17         if(a[p1]<=a[p2])

18         {

19             temp[p++]=a[p1++];

20             continue;

21         }

22         else 

23         {

24             temp[p++]=a[p2++];

25             ans+=e1-p1+1;   //关键所在

26             continue;

27         }

28     }

29     while(p1<=e1) temp[p++]=a[p1++];

30     while(p2<=e2) temp[p++]=a[p2++];

31     int i;

32     for(i=s1;i<=e2;i++) a[i]=temp[i-s1];

33     delete temp;

34 }

35 

36 void merge_sort(int s,int e)

37 {

38     int m;

39     if(s<e)

40     {

41         m=(s+e)/2;

42         merge_sort(s,m);

43         merge_sort(m+1,e);

44         merge(s,m,m+1,e);

45     }

46 }

47 

48 int main()

49 {

50     int test;

51     scanf("%d",&test);

52     while(test--)

53     {

54         int n,i;

55         ans=0;

56         scanf("%d",&n);

57         for(i=0;i<n;i++)

58             scanf("%d",&a[i]);

59         merge_sort(0,n-1);

60         printf("%lld\n",ans);

61     }

62 }        

 

你可能感兴趣的:(归并)