归并法求逆序数

本文介绍了一种使用归并排序算法高效计算序列逆序数的方法。逆序数是指在一个序列中,前面的数大于后面数的对数总和。文章通过示例解释了逆序数的概念,并提供了一个C++实现的例子,该例子能够处理多达一百万个元素的序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求逆序数
时间限制: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 }        

 

任务描述 本关任务:编写一个能计算数组中逆序数的小程序。 给定一个整数数组 A = { a0,a1,... ,an-1 } ,若 i < j 且 ai > aj ,则 <ai , aj> 就是一个逆序对。例如数组 {3,1,4,5,2} 的逆序对有<3, 1>,<3, 2>,<4, 2>,<5, 2>。编写一个采用分治数组 A 中逆序对的个数,即逆序数。 输入格式 第一行输入数组元素个数 n(2<=n<=104)。 第二行输入n 个数组元素,各个元素用空格分隔。 输出格式 输出逆序数。 编程要 系统主函数如下: main.cpp #include <cstdio> #define MAX 10000 // 全局变量ans,累计逆序数 extern int ans; // 用二路归并逆序数 void reversepairs(int a[], int n); int main() { int i, n, a[MAX]; // Input scanf("%d", &n); for (i = 0; i < n; i++) scanf("%d", &a[i]); // Calculate reversepairs(a, n); // Output printf("%d\n", ans); return 0; } 根据提示,在右侧编辑器补充代码,计算并输出数组中的逆序数。 reversepairs.cpp // 全局变量ans,累计逆序数 int ans; // 归并操作函数,将两个有序子数组合并为一个有序数组 void merge(int a[], int low, int mid, int high) { int i, j, k; // 临时辅助数组b int b[high - low + 1]; /********** begin **********/ /********** end **********/ } // 递归二路归并排序 void mergesort(int a[], int low, int high) { /********** begin **********/ /********** end **********/ } // 用二路归并逆序数 void reversepairs(int a[], int n) { ans = 0; mergesort(a, 0, n - 1); } 测试说明 测试输入: 5 3 1 4 5 2 预期输出: 4
最新发布
03-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值