归并法求逆序数

求逆序数

时间限制: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 }        
原文地址:https://www.cnblogs.com/hxsyl/p/2947309.html